Contract Overview
Balance: 0 Ether
Ether Value: $0
Transactions: 3 txns
Misc:
Address Watch: Add To Watch List
Contract Creator: 0xb5af4138f0f33be0d6414eb25271b9c2dc245fb5at txn 0xef673e21969abe6dca6c0a3b036bdd9214b45bae9250bc6779534223ccd68edc
 Latest 3 txns

TxHash Age From To Value [TxFee]
0xe7876638dbd3bed2b2e28e7c22638889e51dad8b43051559e1061af9869f07c961 days 17 hrs ago0x010afb8548a5d1a3a3d62f58ca0a5a1329974206  IN   0xcbaa6ea4886b535fc7abace3f3985ed03b3b80a00 Ether0.00039033
0x678685e6f8cb006242a9ef745f5ee910171a8f8bfecf1134bf1ba98227fa064561 days 17 hrs ago0x010afb8548a5d1a3a3d62f58ca0a5a1329974206  IN   0xcbaa6ea4886b535fc7abace3f3985ed03b3b80a00 Ether0.000087392
0xef673e21969abe6dca6c0a3b036bdd9214b45bae9250bc6779534223ccd68edc111 days 9 hrs ago0xb5af4138f0f33be0d6414eb25271b9c2dc245fb5  IN    Contract Creation0 Ether0.050071779
[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
View All
ParentTxHash Block Age From To Value
Warning: The Compiled Contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity), NestedArrayFunctionCallDecoder (medium-severity) SolidityCompiler Bugs.

Contract Source Code Verified (Exact Match)
Contract Name: BondingManager
Compiler Text: v0.4.18+commit.9cf6e910
Optimization Enabled: Yes
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

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);
        }
    }
}

/**
 * @title EarningsPool
 * @dev Manages reward and fee pools for delegators and transcoders
 */
library EarningsPool {
    using SafeMath for uint256;

    // Represents rewards and fees to be distributed to delegators
    // The `hasTranscoderRewardFeePool` flag was introduced so that EarningsPool.Data structs used by the BondingManager
    // created with older versions of this library can be differentiated from EarningsPool.Data structs used by the BondingManager
    // created with a newer version of this library. If the flag is true, then the struct was initialized using the `init` function
    // using a newer version of this library meaning that it is using separate transcoder reward and fee pools
    struct Data {
        uint256 rewardPool;                // Delegator rewards. If `hasTranscoderRewardFeePool` is false, this will contain transcoder rewards as well
        uint256 feePool;                   // Delegator fees. If `hasTranscoderRewardFeePool` is false, this will contain transcoder fees as well
        uint256 totalStake;                // Transcoder's total stake during the earnings pool's round
        uint256 claimableStake;            // Stake that can be used to claim portions of the fee and reward pools
        uint256 transcoderRewardCut;       // Transcoder's reward cut during the earnings pool's round
        uint256 transcoderFeeShare;        // Transcoder's fee share during the earnings pool's round
        uint256 transcoderRewardPool;      // Transcoder rewards. If `hasTranscoderRewardFeePool` is false, this should always be 0
        uint256 transcoderFeePool;         // Transcoder fees. If `hasTranscoderRewardFeePool` is false, this should always be 0
        bool hasTranscoderRewardFeePool;   // Flag to indicate if the earnings pool has separate transcoder reward and fee pools
    }

    /**
     * @dev Initialize a EarningsPool struct
     * @param earningsPool Storage pointer to EarningsPool struct
     * @param _stake Total stake of the transcoder during the earnings pool's round
     * @param _rewardCut Reward cut of transcoder during the earnings pool's round
     * @param _feeShare Fee share of transcoder during the earnings pool's round
     */
    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;
        // We set this flag to true here to differentiate between EarningsPool structs created using older versions of this library.
        // When using a version of this library after the introduction of this flag to read an EarningsPool struct created using an older version
        // of this library, this flag should be false in the returned struct because the default value for EVM storage is 0
        earningsPool.hasTranscoderRewardFeePool = true;
    }

    /**
     * @dev Return whether this earnings pool has claimable shares i.e. is there unclaimed stake
     * @param earningsPool Storage pointer to EarningsPool struct
     */
    function hasClaimableShares(EarningsPool.Data storage earningsPool) internal view returns (bool) {
        return earningsPool.claimableStake > 0;
    }

    /** 
     * @dev Add fees to the earnings pool
     * @param earningsPool Storage pointer to EarningsPools struct
     * @param _fees Amount of fees to add
     */
    function addToFeePool(EarningsPool.Data storage earningsPool, uint256 _fees) internal {
        if (earningsPool.hasTranscoderRewardFeePool) {
            // If the earnings pool has a separate transcoder fee pool, calculate the portion of incoming fees
            // to put into the delegator fee pool and the portion to put into the transcoder fee pool
            uint256 delegatorFees = MathUtils.percOf(_fees, earningsPool.transcoderFeeShare);
            earningsPool.feePool = earningsPool.feePool.add(delegatorFees);
            earningsPool.transcoderFeePool = earningsPool.transcoderFeePool.add(_fees.sub(delegatorFees));
        } else {
            // If the earnings pool does not have a separate transcoder fee pool, put all the fees into the delegator fee pool
            earningsPool.feePool = earningsPool.feePool.add(_fees);
        }
    }

    /** 
     * @dev Add rewards to the earnings pool
     * @param earningsPool Storage pointer to EarningsPool struct
     * @param _rewards Amount of rewards to add
     */
    function addToRewardPool(EarningsPool.Data storage earningsPool, uint256 _rewards) internal {
        if (earningsPool.hasTranscoderRewardFeePool) {
            // If the earnings pool has a separate transcoder reward pool, calculate the portion of incoming rewards
            // to put into the delegator reward pool and the portion to put into the transcoder reward pool
            uint256 transcoderRewards = MathUtils.percOf(_rewards, earningsPool.transcoderRewardCut);
            earningsPool.rewardPool = earningsPool.rewardPool.add(_rewards.sub(transcoderRewards));
            earningsPool.transcoderRewardPool = earningsPool.transcoderRewardPool.add(transcoderRewards);
        } else {
            // If the earnings pool does not have a separate transcoder reward pool, put all the rewards into the delegator reward pool
            earningsPool.rewardPool = earningsPool.rewardPool.add(_rewards);
        }
    }

    /**
     * @dev Claim reward and fee shares which decreases the reward/fee pools and the remaining claimable stake
     * @param earningsPool Storage pointer to EarningsPool struct
     * @param _stake Stake of claimant
     * @param _isTranscoder Flag indicating whether the claimant is a transcoder
     */
    function claimShare(EarningsPool.Data storage earningsPool, uint256 _stake, bool _isTranscoder) internal returns (uint256, uint256) {
        uint256 totalFees = 0;
        uint256 totalRewards = 0;
        uint256 delegatorFees = 0;
        uint256 transcoderFees = 0;
        uint256 delegatorRewards = 0;
        uint256 transcoderRewards = 0;

        if (earningsPool.hasTranscoderRewardFeePool) {
            // EarningsPool has transcoder reward and fee pools
            // Compute fee share
            (delegatorFees, transcoderFees) = feePoolShareWithTranscoderRewardFeePool(earningsPool, _stake, _isTranscoder);
            totalFees = delegatorFees.add(transcoderFees);
            // Compute reward share
            (delegatorRewards, transcoderRewards) = rewardPoolShareWithTranscoderRewardFeePool(earningsPool, _stake, _isTranscoder);
            totalRewards = delegatorRewards.add(transcoderRewards);

            // Fee pool only holds delegator fees when `hasTranscoderRewardFeePool` is true - deduct delegator fees
            earningsPool.feePool = earningsPool.feePool.sub(delegatorFees);
            // Reward pool only holds delegator rewards when `hasTranscoderRewardFeePool` is true - deduct delegator rewards
            earningsPool.rewardPool = earningsPool.rewardPool.sub(delegatorRewards);

            if (_isTranscoder) {
                // Claiming as a transcoder
                // Clear transcoder fee pool
                earningsPool.transcoderFeePool = 0;
                // Clear transcoder reward pool
                earningsPool.transcoderRewardPool = 0;
            }
        } else {
            // EarningsPool does not have transcoder reward and fee pools
            // Compute fee share
            (delegatorFees, transcoderFees) = feePoolShareNoTranscoderRewardFeePool(earningsPool, _stake, _isTranscoder);
            totalFees = delegatorFees.add(transcoderFees);
            // Compute reward share
            (delegatorRewards, transcoderRewards) = rewardPoolShareNoTranscoderRewardFeePool(earningsPool, _stake, _isTranscoder);
            totalRewards = delegatorRewards.add(transcoderRewards);

            // Fee pool holds delegator and transcoder fees when `hasTranscoderRewardFeePool` is false - deduct delegator and transcoder fees
            earningsPool.feePool = earningsPool.feePool.sub(totalFees);
            // Reward pool holds delegator and transcoder fees when `hasTranscoderRewardFeePool` is false - deduct delegator and transcoder fees
            earningsPool.rewardPool = earningsPool.rewardPool.sub(totalRewards);
        }

        // Update remaining claimable stake
        earningsPool.claimableStake = earningsPool.claimableStake.sub(_stake);

        return (totalFees, totalRewards);
    }

    /** 
     * @dev Returns the fee pool share for a claimant. If the claimant is a transcoder, include transcoder fees as well.
     * @param earningsPool Storage pointer to EarningsPool struct
     * @param _stake Stake of claimant
     * @param _isTranscoder Flag indicating whether the claimant is a transcoder
     */
    function feePoolShare(EarningsPool.Data storage earningsPool, uint256 _stake, bool _isTranscoder) internal view returns (uint256) {
        uint256 delegatorFees = 0;
        uint256 transcoderFees = 0;

        if (earningsPool.hasTranscoderRewardFeePool) {
            (delegatorFees, transcoderFees) = feePoolShareWithTranscoderRewardFeePool(earningsPool, _stake, _isTranscoder);
        } else {
            (delegatorFees, transcoderFees) = feePoolShareNoTranscoderRewardFeePool(earningsPool, _stake, _isTranscoder);
        }

        return delegatorFees.add(transcoderFees);
    }

    /** 
     * @dev Returns the reward pool share for a claimant. If the claimant is a transcoder, include transcoder rewards as well.
     * @param earningsPool Storage pointer to EarningsPool struct
     * @param _stake Stake of claimant
     * @param _isTranscoder Flag indicating whether the claimant is a transcoder
     */
    function rewardPoolShare(EarningsPool.Data storage earningsPool, uint256 _stake, bool _isTranscoder) internal view returns (uint256) {
        uint256 delegatorRewards = 0;
        uint256 transcoderRewards = 0;

        if (earningsPool.hasTranscoderRewardFeePool) {
            (delegatorRewards, transcoderRewards) = rewardPoolShareWithTranscoderRewardFeePool(earningsPool, _stake, _isTranscoder);
        } else {
            (delegatorRewards, transcoderRewards) = rewardPoolShareNoTranscoderRewardFeePool(earningsPool, _stake, _isTranscoder);
        }

        return delegatorRewards.add(transcoderRewards);
    }

    /** 
     * @dev Helper function to calculate fee pool share if the earnings pool has a separate transcoder fee pool
     * @param earningsPool Storage pointer to EarningsPool struct
     * @param _stake Stake of claimant
     * @param _isTranscoder Flag indicating whether the claimant is a transcoder
     */
    function feePoolShareWithTranscoderRewardFeePool(
        EarningsPool.Data storage earningsPool,
        uint256 _stake,
        bool _isTranscoder
    ) 
        internal
        view
        returns (uint256, uint256)
    {
        // If there is no claimable stake, the fee pool share is 0
        // If there is claimable stake, calculate fee pool share based on remaining amount in fee pool, remaining claimable stake and claimant's stake
        uint256 delegatorFees = earningsPool.claimableStake > 0 ? MathUtils.percOf(earningsPool.feePool, _stake, earningsPool.claimableStake) : 0;

        // If claimant is a transcoder, include transcoder fee pool as well
        return _isTranscoder ? (delegatorFees, earningsPool.transcoderFeePool) : (delegatorFees, 0);
    }

    /** 
     * @dev Helper function to calculate reward pool share if the earnings pool has a separate transcoder reward pool
     * @param earningsPool Storage pointer to EarningsPool struct
     * @param _stake Stake of claimant
     * @param _isTranscoder Flag indicating whether the claimant is a transcoder
     */
    function rewardPoolShareWithTranscoderRewardFeePool(
        EarningsPool.Data storage earningsPool,
        uint256 _stake,
        bool _isTranscoder
    )
        internal
        view
        returns (uint256, uint256)
    {
        // If there is no claimable stake, the reward pool share is 0
        // If there is claimable stake, calculate reward pool share based on remaining amount in reward pool, remaining claimable stake and claimant's stake
        uint256 delegatorRewards = earningsPool.claimableStake > 0 ? MathUtils.percOf(earningsPool.rewardPool, _stake, earningsPool.claimableStake) : 0;

        // If claimant is a transcoder, include transcoder reward pool as well
        return _isTranscoder ? (delegatorRewards, earningsPool.transcoderRewardPool) : (delegatorRewards, 0);
    }
   
    /**
     * @dev Helper function to calculate the fee pool share if the earnings pool does not have a separate transcoder fee pool
     * This implements calculation logic from a previous version of this library
     * @param earningsPool Storage pointer to EarningsPool struct
     * @param _stake Stake of claimant
     * @param _isTranscoder Flag indicating whether the claimant is a transcoder
     */
    function feePoolShareNoTranscoderRewardFeePool(
        EarningsPool.Data storage earningsPool,
        uint256 _stake,
        bool _isTranscoder
    ) 
        internal
        view
        returns (uint256, 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, transcoderFees);
        } else {
            return (delegatorFees, 0);
        }
    }

    /**
     * @dev Helper function to calculate the reward pool share if the earnings pool does not have a separate transcoder reward pool
     * This implements calculation logic from a previous version of this library
     * @param earningsPool Storage pointer to EarningsPool struct
     * @param _stake Stake of claimant
     * @param _isTranscoder Flag indicating whether the claimant is a transcoder
     */
    function rewardPoolShareNoTranscoderRewardFeePool(
        EarningsPool.Data storage earningsPool,
        uint256 _stake,
        bool _isTranscoder
    )
        internal
        view
        returns (uint256, 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, transcoderRewards);
        } else {
            return (delegatorRewards, 0);
        }
    }
}

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
 * TODO: switch to interface type
 */
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 newDelegate, address indexed oldDelegate, address indexed delegator, uint256 additionalAmount, uint256 bondedAmount);
    event Unbond(address indexed delegate, address indexed delegator, uint256 unbondingLockId, uint256 amount, uint256 withdrawRound);
    event Rebond(address indexed delegate, address indexed delegator, uint256 unbondingLockId, uint256 amount);
    event WithdrawStake(address indexed delegator, uint256 unbondingLockId, uint256 amount, uint256 withdrawRound);
    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 withdrawRoundDEPRECATED;         // DEPRECATED - DO NOT USE
        uint256 lastClaimRound;                  // The last round during which the delegator claimed its earnings
        uint256 nextUnbondingLockId;             // ID for the next unbonding lock created
        mapping (uint256 => UnbondingLock) unbondingLocks; // Mapping of unbonding lock ID => unbonding lock
    }

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

    // Represents an amount of tokens that are being unbonded
    struct UnbondingLock {
        uint256 amount;              // Amount of tokens being unbonded
        uint256 withdrawRound;       // Round at which unbonding period is over and tokens can be withdrawn
    }

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

    // DEPRECATED - DO NOT USE
    // The function getTotalBonded() no longer uses this variable
    // and instead calculates the total bonded value separately
    uint256 private totalBondedDEPRECATED;

    // 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 > transcoderTotalStake(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;
        // Current delegate
        address currentDelegate = del.delegateAddress;

        if (delegatorStatus(msg.sender) == DelegatorStatus.Unbonded) {
            // 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);
            // Unbonded state = no existing delegate and no bonded stake
            // Thus, delegation amount = provided amount
        } 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[currentDelegate].delegatedAmount = delegators[currentDelegate].delegatedAmount.sub(del.bondedAmount);

            if (transcoderStatus(currentDelegate) == TranscoderStatus.Registered) {
                // Previously delegated to a transcoder
                // Decrease old transcoder's total stake
                transcoderPool.updateKey(currentDelegate, transcoderTotalStake(currentDelegate).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, transcoderTotalStake(del.delegateAddress).add(delegationAmount), address(0), address(0));
        }

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

        Bond(_to, currentDelegate, msg.sender, _amount, del.bondedAmount);
    }

    /**
     * @dev Unbond an amount of the delegator's bonded stake
     * @param _amount Amount of tokens to unbond
     */
    function unbond(uint256 _amount)
        external
        whenSystemNotPaused
        currentRoundInitialized
        autoClaimEarnings
    {
        // Caller must be in bonded state
        require(delegatorStatus(msg.sender) == DelegatorStatus.Bonded);

        Delegator storage del = delegators[msg.sender];

        // Amount must be greater than 0
        require(_amount > 0);
        // Amount to unbond must be less than or equal to current bonded amount 
        require(_amount <= del.bondedAmount);

        address currentDelegate = del.delegateAddress;
        uint256 currentRound = roundsManager().currentRound();
        uint256 withdrawRound = currentRound.add(unbondingPeriod);
        uint256 unbondingLockId = del.nextUnbondingLockId;

        // Create new unbonding lock
        del.unbondingLocks[unbondingLockId] = UnbondingLock({
            amount: _amount,
            withdrawRound: withdrawRound
        });
        // Increment ID for next unbonding lock
        del.nextUnbondingLockId = unbondingLockId.add(1);
        // Decrease delegator's bonded amount
        del.bondedAmount = del.bondedAmount.sub(_amount);
        // Decrease delegate's delegated amount
        delegators[del.delegateAddress].delegatedAmount = delegators[del.delegateAddress].delegatedAmount.sub(_amount);

        if (transcoderStatus(del.delegateAddress) == TranscoderStatus.Registered && (del.delegateAddress != msg.sender || del.bondedAmount > 0)) {
            // A transcoder's delegated stake within the registered pool needs to be decreased if:
            // - The caller's delegate is a registered transcoder
            // - Caller is not delegated to self OR caller is delegated to self and has a non-zero bonded amount
            // If the caller is delegated to self and has a zero bonded amount, it will be removed from the 
            // transcoder pool so its delegated stake within the pool does not need to be decreased
            transcoderPool.updateKey(del.delegateAddress, transcoderTotalStake(del.delegateAddress).sub(_amount), address(0), address(0));
        }

        // Check if delegator has a zero bonded amount
        // If so, update its delegation status
        if (del.bondedAmount == 0) {
            // Delegator no longer delegated to anyone if it does not have a bonded amount
            del.delegateAddress = address(0);
            // Delegator does not have a start round if it is no longer delegated to anyone
            del.startRound = 0;

            if (transcoderStatus(msg.sender) == TranscoderStatus.Registered) {
                // If caller is a registered transcoder and is no longer bonded, resign
                resignTranscoder(msg.sender);
            }
        } 

        Unbond(currentDelegate, msg.sender, unbondingLockId, _amount, withdrawRound);
    }

    /**
     * @dev Rebond tokens for an unbonding lock to a delegator's current delegate while a delegator
     * is in the Bonded or Pending states
     * @param _unbondingLockId ID of unbonding lock to rebond with
     */
    function rebond(
        uint256 _unbondingLockId
    ) 
        external
        whenSystemNotPaused
        currentRoundInitialized 
        autoClaimEarnings
    {
        // Caller must not be an unbonded delegator
        require(delegatorStatus(msg.sender) != DelegatorStatus.Unbonded);

        // Process rebond using unbonding lock
        processRebond(msg.sender, _unbondingLockId);
    }

    /**
     * @dev Rebond tokens for an unbonding lock to a delegate while a delegator
     * is in the Unbonded state
     * @param _to Address of delegate
     * @param _unbondingLockId ID of unbonding lock to rebond with
     */
    function rebondFromUnbonded(
        address _to,
        uint256 _unbondingLockId
    )
        external
        whenSystemNotPaused
        currentRoundInitialized
        autoClaimEarnings
    {
        // Caller must be an unbonded delegator
        require(delegatorStatus(msg.sender) == DelegatorStatus.Unbonded);

        // Set delegator's start round and transition into Pending state
        delegators[msg.sender].startRound = roundsManager().currentRound().add(1);
        // Set delegator's delegate
        delegators[msg.sender].delegateAddress = _to;
        // Process rebond using unbonding lock
        processRebond(msg.sender, _unbondingLockId);
    }

    /**
     * @dev Withdraws tokens for an unbonding lock that has existed through an unbonding period
     * @param _unbondingLockId ID of unbonding lock to withdraw with
     */
    function withdrawStake(uint256 _unbondingLockId)
        external
        whenSystemNotPaused
        currentRoundInitialized
    {
        Delegator storage del = delegators[msg.sender];
        UnbondingLock storage lock = del.unbondingLocks[_unbondingLockId];

        // Unbonding lock must be valid
        require(isValidUnbondingLock(msg.sender, _unbondingLockId));
        // Withdrawal must be valid for the unbonding lock i.e. the withdraw round is now or in the past
        require(lock.withdrawRound <= roundsManager().currentRound());

        uint256 amount = lock.amount;
        uint256 withdrawRound = lock.withdrawRound;
        // Delete unbonding lock
        delete del.unbondingLocks[_unbondingLockId];

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

        WithdrawStake(msg.sender, _unbondingLockId, amount, withdrawRound);
    }

    /**
     * @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 = transcoderTotalStake(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.addToFeePool(_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);
            }

            // 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.bondedAmount == 0) {
            // Delegator unbonded all its tokens
            return DelegatorStatus.Unbonded;
        } 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, uint256 transcoderRewardCut, uint256 transcoderFeeShare, uint256 transcoderRewardPool, uint256 transcoderFeePool, bool hasTranscoderRewardFeePool)
    {
        EarningsPool.Data storage earningsPool = transcoders[_transcoder].earningsPoolPerRound[_round];

        rewardPool = earningsPool.rewardPool;
        feePool = earningsPool.feePool;
        totalStake = earningsPool.totalStake;
        claimableStake = earningsPool.claimableStake;
        transcoderRewardCut = earningsPool.transcoderRewardCut;
        transcoderFeeShare = earningsPool.transcoderFeeShare;
        transcoderRewardPool = earningsPool.transcoderRewardPool;
        transcoderFeePool = earningsPool.transcoderFeePool;
        hasTranscoderRewardFeePool = earningsPool.hasTranscoderRewardFeePool;
    }

    /**
     * @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 lastClaimRound, uint256 nextUnbondingLockId)
    {
        Delegator storage del = delegators[_delegator];

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

    /**
     * @dev Return delegator's unbonding lock info
     * @param _delegator Address of delegator
     * @param _unbondingLockId ID of unbonding lock
     */
    function getDelegatorUnbondingLock(
        address _delegator,
        uint256 _unbondingLockId
    ) 
        public
        view
        returns (uint256 amount, uint256 withdrawRound) 
    {
        UnbondingLock storage lock = delegators[_delegator].unbondingLocks[_unbondingLockId];

        return (lock.amount, lock.withdrawRound);
    }

    /**
     * @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) {
        uint256 totalBonded = 0;
        uint256 totalTranscoders = transcoderPool.getSize();
        address currentTranscoder = transcoderPool.getFirst();

        for (uint256 i = 0; i < totalTranscoders; i++) {
            // Add current transcoder's total delegated stake to total bonded counter
            totalBonded = totalBonded.add(transcoderTotalStake(currentTranscoder));
            // Get next transcoder in the pool
            currentTranscoder = transcoderPool.getNext(currentTranscoder);
        }

        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 Return whether an unbonding lock for a delegator is valid
     * @param _delegator Address of delegator
     * @param _unbondingLockId ID of unbonding lock
     */
    function isValidUnbondingLock(address _delegator, uint256 _unbondingLockId) public view returns (bool) {
        // A unbonding lock is only valid if it has a non-zero withdraw round (the default value is zero)
        return delegators[_delegator].unbondingLocks[_unbondingLockId].withdrawRound > 0;
    }

    /**
     * @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.addToRewardPool(_rewards);
        // Update transcoder's delegated amount with rewards
        del.delegatedAmount = del.delegatedAmount.add(_rewards);
        // Update transcoder's total stake with rewards
        uint256 newStake = transcoderTotalStake(_transcoder).add(_rewards);
        transcoderPool.updateKey(_transcoder, newStake, address(0), address(0));
    }

    /**
     * @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 Update the state of a delegator and its delegate by processing a rebond using an unbonding lock
     * @param _delegator Address of delegator
     * @param _unbondingLockId ID of unbonding lock to rebond with
     */
    function processRebond(address _delegator, uint256 _unbondingLockId) internal {
        Delegator storage del = delegators[_delegator];
        UnbondingLock storage lock = del.unbondingLocks[_unbondingLockId];

        // Unbonding lock must be valid
        require(isValidUnbondingLock(_delegator, _unbondingLockId));

        uint256 amount = lock.amount;
        // Increase delegator's bonded amount
        del.bondedAmount = del.bondedAmount.add(amount);
        // Increase delegate's delegated amount
        delegators[del.delegateAddress].delegatedAmount = delegators[del.delegateAddress].delegatedAmount.add(amount);

        if (transcoderStatus(del.delegateAddress) == TranscoderStatus.Registered) {
            // If delegate is a registered transcoder increase its delegated stake in registered pool
            transcoderPool.updateKey(del.delegateAddress, transcoderTotalStake(del.delegateAddress).add(amount), address(0), address(0));
        }

        // Delete lock
        delete del.unbondingLocks[_unbondingLockId];

        Rebond(del.delegateAddress, _delegator, _unbondingLockId, amount);
    }

    /**
     * @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 ABI  
[{"constant":true,"inputs":[],"name":"maxEarningsClaimsRounds","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_delegator","type":"address"},{"name":"_unbondingLockId","type":"uint256"}],"name":"isValidUnbondingLock","outputs":[{"name":"","type":"bool"}],"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"},{"name":"transcoderRewardCut","type":"uint256"},{"name":"transcoderFeeShare","type":"uint256"},{"name":"transcoderRewardPool","type":"uint256"},{"name":"transcoderFeePool","type":"uint256"},{"name":"hasTranscoderRewardFeePool","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_endRound","type":"uint256"}],"name":"claimEarnings","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_unbondingLockId","type":"uint256"}],"name":"withdrawStake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"unbond","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":"_to","type":"address"},{"name":"_unbondingLockId","type":"uint256"}],"name":"rebondFromUnbonded","outputs":[],"payable":false,"stateMutability":"nonpayable","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":true,"inputs":[{"name":"_delegator","type":"address"},{"name":"_unbondingLockId","type":"uint256"}],"name":"getDelegatorUnbondingLock","outputs":[{"name":"amount","type":"uint256"},{"name":"withdrawRound","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":"_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":"lastClaimRound","type":"uint256"},{"name":"nextUnbondingLockId","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":"_unbondingLockId","type":"uint256"}],"name":"rebond","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":"newDelegate","type":"address"},{"indexed":true,"name":"oldDelegate","type":"address"},{"indexed":true,"name":"delegator","type":"address"},{"indexed":false,"name":"additionalAmount","type":"uint256"},{"indexed":false,"name":"bondedAmount","type":"uint256"}],"name":"Bond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"delegate","type":"address"},{"indexed":true,"name":"delegator","type":"address"},{"indexed":false,"name":"unbondingLockId","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"withdrawRound","type":"uint256"}],"name":"Unbond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"delegate","type":"address"},{"indexed":true,"name":"delegator","type":"address"},{"indexed":false,"name":"unbondingLockId","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Rebond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"delegator","type":"address"},{"indexed":false,"name":"unbondingLockId","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"withdrawRound","type":"uint256"}],"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"}]

  Contract Creation Code Switch To Opcodes View
6060604052341561000f57600080fd5b6040516020806150e28339810160405280805160008054600160a060020a03909216600160a060020a0319909216919091179055505061508e806100546000396000f3006060604052600436106101f55763ffffffff60e060020a600035041663038424c381146101fa5780630fd02fc11461021f5780631544fc6714610255578063228cb7331461029857806322bf9d7c146102ad578063235c9603146102d8578063242ed69f1461031357806324454fc41461032657806324b1babf1461039557806325d5971f146103ab57806327de9e32146103c15780632a4e0d55146103d75780633a080e93146103ea5780633aeb512c1461040c5780633da1c2f514610431578063412f83b614610447578063476343ee1461048157806351720b41146104945780635a2a75a9146104a75780635c50c356146104ba5780635dce9948146104cd57806360c79d001461052a57806361e25d2314610540578063673a456b1461055357806368ba170c146105695780636cf6d6751461058857806372d9f13d146105b857806377517765146105ce5780637c0207cb146105e457806385aaff621461060657806388a6c749146106225780638b2f16521461063557806391fdf6b11461066457806392eefe9b146106805780639d0b2c7a1461069f5780639ef9df94146106c1578063a64ad595146106e0578063b78d27dc14610751578063eaffb3f914610773578063f10d1de114610789578063f2083220146107a9578063f595f1cc146107cb578063f77c4791146107ed575b600080fd5b341561020557600080fd5b61020d610800565b60405190815260200160405180910390f35b341561022a57600080fd5b610241600160a060020a0360043516602435610806565b604051901515815260200160405180910390f35b341561026057600080fd5b610274600160a060020a0360043516610837565b6040518082600281111561028457fe5b60ff16815260200191505060405180910390f35b34156102a357600080fd5b6102ab610974565b005b34156102b857600080fd5b6102ab600160a060020a0360043581169060243516604435606435610c13565b34156102e357600080fd5b6102f7600160a060020a03600435166110d0565b604051600160a060020a03909116815260200160405180910390f35b341561031e57600080fd5b6102ab61115b565b341561033157600080fd5b610348600160a060020a0360043516602435611649565b60405198895260208901979097526040808901969096526060880194909452608087019290925260a086015260c085015260e0840152901515610100830152610120909101905180910390f35b34156103a057600080fd5b6102ab6004356116b0565b34156103b657600080fd5b6102ab60043561183a565b34156103cc57600080fd5b6102ab600435611ac6565b34156103e257600080fd5b61020d611f81565b34156103f557600080fd5b6102ab600160a060020a0360043516602435611ffb565b341561041757600080fd5b6102ab600160a060020a03600435166024356044356121d9565b341561043c57600080fd5b61020d600435612364565b341561045257600080fd5b610469600160a060020a0360043516602435612379565b60405191825260208201526040908101905180910390f35b341561048c57600080fd5b6102ab6123ad565b341561049f57600080fd5b61020d612588565b34156104b257600080fd5b61020d61258e565b34156104c557600080fd5b61020d6125e8565b34156104d857600080fd5b6104ec600160a060020a0360043516612795565b60405196875260208701959095526040808701949094526060860192909252608085015260a084015260c083019190915260e0909101905180910390f35b341561053557600080fd5b6102ab6004356127de565b341561054b57600080fd5b61020d612930565b341561055e57600080fd5b6102ab600435612936565b341561057457600080fd5b610241600160a060020a0360043516612a94565b341561059357600080fd5b61059b612ab3565b60405167ffffffffffffffff909116815260200160405180910390f35b34156105c357600080fd5b6102ab600435612ac3565b34156105d957600080fd5b61020d600435612ba1565b34156105ef57600080fd5b610241600160a060020a0360043516602435612bb6565b341561061157600080fd5b6102ab600435602435604435612be4565b341561062d57600080fd5b6102f7613460565b341561064057600080fd5b610654600160a060020a03600435166134ba565b6040518082600181111561028457fe5b341561066f57600080fd5b6102f7600435602435604435613553565b341561068b57600080fd5b6102ab600160a060020a0360043516613724565b34156106aa57600080fd5b61020d600160a060020a03600435166024356137a7565b34156106cc57600080fd5b61020d600160a060020a03600435166138da565b34156106eb57600080fd5b6106ff600160a060020a0360043516613943565b6040518088815260200187815260200186600160a060020a0316600160a060020a0316815260200185815260200184815260200183815260200182815260200197505050505050505060405180910390f35b341561075c57600080fd5b6102ab600435600160a060020a036024351661398f565b341561077e57600080fd5b6102ab600435613f33565b341561079457600080fd5b6102ab67ffffffffffffffff6004351661404b565b34156107b457600080fd5b61020d600160a060020a0360043516602435614141565b34156107d657600080fd5b61020d600160a060020a03600435166024356141a5565b34156107f857600080fd5b6102f7614311565b60045481565b600160a060020a03821660009081526005602090815260408083208484526008019091528120600101541192915050565b600160a060020a038116600090815260056020526040812080541515610860576002915061096e565b610868614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156108ad57600080fd5b6102c65a03f115156108be57600080fd5b50505060405180519050816004015411156108dc576000915061096e565b6000816004015411801561095b57506108f3614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561093857600080fd5b6102c65a03f1151561094957600080fd5b50505060405180519050816004015411155b15610969576001915061096e565b600291505b50919050565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156109be57600080fd5b6102c65a03f115156109cf57600080fd5b50505060405180511590506109e357600080fd5b6109eb614320565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610a3057600080fd5b6102c65a03f11515610a4157600080fd5b505050604051805190501515610a5657600080fd5b610a5e614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610aa357600080fd5b6102c65a03f11515610ab457600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a033316845260010190915290205490935060ff1615159050610af557600080fd5b600160a060020a033316600090815260066020526040902054821415610b1a57600080fd5b600160a060020a0333166000908152600660205260409020829055610b3d6143b3565b600160a060020a0316637dbedad5610b553385614141565b6000858152600d6020526040808220600201549190516020015260405160e060020a63ffffffff851602815260048101929092526024820152604401602060405180830381600087803b1515610baa57600080fd5b6102c65a03f11515610bbb57600080fd5b505050604051805190509050610bd2338284614435565b33600160a060020a03167f619caafabdd75649b302ba8419e48cccf64f37f1983ac4727cfb38b57703ffc98260405190815260200160405180910390a25050565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610c6157600080fd5b6102c65a03f11515610c7257600080fd5b5050506040518051159050610c8657600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610d0757600080fd5b6102c65a03f11515610d1857600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515610d4157600080fd5b600160a060020a03881660009081526005602052604081208054909550111561106157600160a060020a038816600090815260056020526040902054610d87908761452a565b8454909350610d9c908463ffffffff61455616565b84556001610da989610837565b6002811115610db457fe5b1415610e0b576002840154600160a060020a0316600090815260056020526040902060030154610dea908463ffffffff61455616565b6002850154600160a060020a03166000908152600560205260409020600301555b6001610e16896134ba565b6001811115610e2157fe5b1415610e3057610e3088614568565b829150600160a060020a03871615610f9557610e4c838661452a565b9050610e566143b3565b600160a060020a031663e7a49c2b888360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515610ea957600080fd5b6102c65a03f11515610eba57600080fd5b505050610ec56143b3565b600160a060020a031663c7ee98c2610ee3848463ffffffff61455616565b60405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610f1957600080fd5b6102c65a03f11515610f2a57600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c228885846040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a261105c565b610f9d6143b3565b600160a060020a031663c7ee98c28360405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610fe257600080fd5b6102c65a03f11515610ff357600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c2260008560006040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b6110c6565b87600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c22886000806040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b5050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561113957600080fd5b6102c65a03f4151561114a57600080fd5b50505060405180519150505b919050565b6000806000806000806000806000806000809054906101000a9004600160a060020a0316600160a060020a0316635c975abb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156111c457600080fd5b6102c65a03f115156111d557600080fd5b50505060405180511590506111e957600080fd5b600054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561126a57600080fd5b6102c65a03f1151561127b57600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156112a457600080fd5b6112ac614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156112f157600080fd5b6102c65a03f1151561130257600080fd5b5050506040518051600354909b5061138e9150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561136e57600080fd5b6102c65a03f4151561137f57600080fd5b50505060405180519050614711565b985060009750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed60088a6040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156113ec57600080fd5b6102c65a03f415156113fd57600080fd5b5050506040518051975060009650505b888610156116295760008a8152600d602052604090208054600181016114338382614fee565b506000918252602080832091909101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038b169081179091558c8352600d8252604080842091845260019182019092529120805460ff19169091179055611498876138da565b94506006600088600160a060020a0316600160a060020a031681526020019081526020016000206004015493506006600088600160a060020a0316600160a060020a031681526020019081526020016000206005015492506006600088600160a060020a0316600160a060020a031681526020019081526020016000206006015491506006600088600160a060020a0316600160a060020a0316815260200190815260200160002090508381600101819055508281600201819055508181600301819055506115888585858460070160008f8152602001908152602001600020614727909392919063ffffffff16565b611598888663ffffffff61475016565b9750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088960006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561160257600080fd5b6102c65a03f4151561161357600080fd5b505050604051805197505060019095019461140d565b50505060009687525050600d602052505060409092206002019190915550565b600160a060020a03909116600090815260066020818152604080842094845260079485019091529091208054600182015460028301546003840154600485015460058601549686015497860154600890960154949893979296919590949193909160ff1690565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156116f957600080fd5b6102c65a03f1151561170a57600080fd5b505050604051805115905061171e57600080fd5b611726614320565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561176b57600080fd5b6102c65a03f1151561177c57600080fd5b50505060405180519050151561179157600080fd5b600160a060020a0333166000908152600560205260409020600601548190106117b957600080fd5b6117c1614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561180657600080fd5b6102c65a03f1151561181757600080fd5b5050506040518051821115905061182d57600080fd5b611837338261476a565b50565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561188857600080fd5b6102c65a03f1151561189957600080fd5b50505060405180511590506118ad57600080fd5b6118b5614320565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156118fa57600080fd5b6102c65a03f1151561190b57600080fd5b50505060405180519050151561192057600080fd5b33600160a060020a03811660009081526005602090815260408083208984526008810190925290912090955093506119589086610806565b151561196357600080fd5b61196b614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156119b057600080fd5b6102c65a03f115156119c157600080fd5b50505060405180516001850154111590506119db57600080fd5b505080546001808301546000868152600886016020526040812081815590920191909155611a076143b3565b600160a060020a031663e7a49c2b338460405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515611a5a57600080fd5b6102c65a03f11515611a6b57600080fd5b50505033600160a060020a03167f1340f1a8f3d456a649e1a12071dfa15655e3d09252131d0f980c3b405cc8dd2e86848460405180848152602001838152602001828152602001935050505060405180910390a25050505050565b600080548190819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611b1657600080fd5b6102c65a03f11515611b2757600080fd5b5050506040518051159050611b3b57600080fd5b611b43614320565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611b8857600080fd5b6102c65a03f11515611b9957600080fd5b505050604051805190501515611bae57600080fd5b611c1f33611bba614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611bff57600080fd5b6102c65a03f11515611c1057600080fd5b5050506040518051905061476a565b6001611c2a33610837565b6002811115611c3557fe5b14611c3f57600080fd5b600160a060020a033316600090815260056020526040812095508611611c6457600080fd5b8454861115611c7257600080fd5b6002850154600160a060020a03169350611c8a614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611ccf57600080fd5b6102c65a03f11515611ce057600080fd5b5050506040518051600254909450611d0a9150849067ffffffffffffffff1663ffffffff61475016565b915084600701549050604080519081016040908152878252602080830185905260008481526008890190915220815181556020820151600191820155611d589150829063ffffffff61475016565b60078601558454611d6f908763ffffffff61455616565b85556002850154600160a060020a0316600090815260056020526040902060030154611da1908763ffffffff61455616565b6002860154600160a060020a031660009081526005602052604090206003015560016002860154611dda90600160a060020a03166134ba565b6001811115611de557fe5b148015611e0f5750600285015433600160a060020a039081169116141580611e0f57508454600090115b15611ecb576002850154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe90600890600160a060020a0316611e5a8a611e4e836138da565b9063ffffffff61455616565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515611eb657600080fd5b6102c65a03f41515611ec757600080fd5b5050505b84541515611f1e5760028501805473ffffffffffffffffffffffffffffffffffffffff19169055600060048601556001611f04336134ba565b6001811115611f0f57fe5b1415611f1e57611f1e33614568565b33600160a060020a031684600160a060020a03167f2d5d98d189bee5496a08db2a5948cb7e5e786f09d17d0c3f228eb41776c24a0683898660405180848152602001838152602001828152602001935050505060405180910390a3505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece586008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515611fdb57600080fd5b6102c65a03f41515611fec57600080fd5b50505060405180519150505b90565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561204457600080fd5b6102c65a03f1151561205557600080fd5b505050604051805115905061206957600080fd5b612071614320565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156120b657600080fd5b6102c65a03f115156120c757600080fd5b5050506040518051905015156120dc57600080fd5b6120e833611bba614320565b60026120f333610837565b60028111156120fe57fe5b1461210857600080fd5b6121816001612115614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561215a57600080fd5b6102c65a03f1151561216b57600080fd5b505050604051805191905063ffffffff61475016565b33600160a060020a03818116600090815260056020526040902060048101939093556002909201805473ffffffffffffffffffffffffffffffffffffffff1916928516929092179091556121d59082614890565b5050565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561222357600080fd5b6102c65a03f1151561223457600080fd5b505050604051805115905061224857600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156122c957600080fd5b6102c65a03f115156122da57600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561230357600080fd5b600161230e866134ba565b600181111561231957fe5b1461232357600080fd5b5050600160a060020a03831660009081526006602090815260408083208484526007810190925290912061235d818563ffffffff614a7b16565b5050505050565b600d6020526000908152604090206002015481565b600160a060020a03919091166000908152600560209081526040808320938352600890930190522080546001909101549091565b60008054600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156123f557600080fd5b6102c65a03f1151561240657600080fd5b505050604051805115905061241a57600080fd5b612422614320565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561246757600080fd5b6102c65a03f1151561247857600080fd5b50505060405180519050151561248d57600080fd5b61249933611bba614320565b600160a060020a033316600090815260056020526040812060010154116124bf57600080fd5b50600160a060020a033316600090815260056020526040812060010180549190556124e86143b3565b600160a060020a03166320283da9338360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b151561253b57600080fd5b6102c65a03f1151561254c57600080fd5b50505033600160a060020a03167fd3719f04262b628e1d01a6ed24707f542cda51f144b5271149c7d0419436d00c60405160405180910390a250565b60015481565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515611fdb57600080fd5b600080808080731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece586008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561264657600080fd5b6102c65a03f4151561265757600080fd5b50505060405180519350731a0b2ca69ca2c7f96e2529faa6d63f881655d81a9050632ebb2fed600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156126bc57600080fd5b6102c65a03f415156126cd57600080fd5b5050506040518051925060009150505b8281101561278c576126fe6126f1836138da565b859063ffffffff61475016565b9350731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088460006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561276857600080fd5b6102c65a03f4151561277957600080fd5b50505060405180519250506001016126dd565b50919392505050565b600160a060020a03166000908152600660208190526040909120805460018201546002830154600384015460048501546005860154959096015493969295919490939192909190565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561282757600080fd5b6102c65a03f1151561283857600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561286157600080fd5b60035481101561287057600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63a176adaf60088360405160e060020a63ffffffff85160281526004810192909252602482015260440160006040518083038186803b15156128c657600080fd5b6102c65a03f415156128d757600080fd5b5050506000805160206150438339815191526040516020808252600e908201527f6e756d5472616e73636f646572730000000000000000000000000000000000006040808301919091526060909101905180910390a150565b60035481565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561297f57600080fd5b6102c65a03f1151561299057600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156129b957600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612a1257600080fd5b6102c65a03f41515612a2357600080fd5b50505060405180518211159050612a3957600080fd5b600381905560008051602061504383398151915260405160208082526014908201527f6e756d4163746976655472616e73636f646572730000000000000000000000006040808301919091526060909101905180910390a150565b60006001612aa1836134ba565b6001811115612aac57fe5b1492915050565b60025467ffffffffffffffff1681565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612b0c57600080fd5b6102c65a03f11515612b1d57600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515612b4657600080fd5b600481905560008051602061504383398151915260405160208082526017908201527f6d61784561726e696e6773436c61696d73526f756e64730000000000000000006040808301919091526060909101905180910390a150565b6000908152600d602052604090206002015490565b6000908152600d60209081526040808320600160a060020a0394909416835260019093019052205460ff1690565b60008054819081908190819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612c3857600080fd5b6102c65a03f11515612c4957600080fd5b5050506040518051159050612c5d57600080fd5b612c65614320565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612caa57600080fd5b6102c65a03f11515612cbb57600080fd5b505050604051805190501515612cd057600080fd5b600160a060020a033316600090815260066020908152604080832060059092529091209097509550612d00614320565b600160a060020a0316636841f2536000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612d4557600080fd5b6102c65a03f11515612d5657600080fd5b505050604051805190501561301c576001612d70336134ba565b6001811115612d7b57fe5b14612d8557600080fd5b60048701548a14612d9557600080fd5b60058701548914612da557600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612dfe57600080fd5b6102c65a03f41515612e0f57600080fd5b5050506040518051600160a060020a0381166000908152600660208190526040822001549197509095509350505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612e9657600080fd5b6102c65a03f41515612ea757600080fd5b50505060405180519050831015612f8c57600160a060020a0385166000908152600660208190526040909120015484901015612efd57600160a060020a0385166000908152600660208190526040909120015493505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088760006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612f6557600080fd5b6102c65a03f41515612f7657600080fd5b5050506040518051955050600190920191612e3d565b838810158015612fa0575086600601548811155b1515612fab57600080fd5b87876006018190555033600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be7886004015489600501548b6001604051938452602084019290925260408084019190915290151560608301526080909101905180910390a2613454565b6130258a614b04565b151561303057600080fd5b61303989614b04565b151561304457600080fd5b600286015433600160a060020a03908116911614801561306657508554600090115b151561307157600080fd5b600487018a90556005870189905560068701889055600386015491506000613098336134ba565b60018111156130a357fe5b141561337557731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634aa12990600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561310257600080fd5b6102c65a03f4151561311357600080fd5b5050506040518051905015156131b657731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a66008338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561319d57600080fd5b6102c65a03f415156131ae57600080fd5b505050613375565b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6372e40b26600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561320f57600080fd5b6102c65a03f4151561322057600080fd5b505050604051805190509050613235816138da565b82111561337557731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088360405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b151561329b57600080fd5b6102c65a03f415156132ac57600080fd5b5050506008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a69091338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561332b57600080fd5b6102c65a03f4151561333c57600080fd5b50505080600160a060020a03167e05588101bf85a737dacb8be2233b33113aaa5c5743525cfbfe2f6a77c2f6ff60405160405180910390a25b33600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be78b8b8b6008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c4790913360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561340d57600080fd5b6102c65a03f4151561341e57600080fd5b50505060405180519050604051938452602084019290925260408084019190915290151560608301526080909101905180910390a25b50505050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515611fdb57600080fd5b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c47600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561352357600080fd5b6102c65a03f4151561353457600080fd5b505050604051805190501561354b57506001611156565b506000611156565b60008061355e615012565b6000848152600d60205260408082205493508190819081908190819081908990518059106135895750595b908082528060200260200182016040525097506000965060009550600094505b888510156136845760008b8152600d602052604090208054869081106135cb57fe5b60009182526020808320909101548d8352600d82526040808420600160a060020a0390921680855260019290920190925291205490945060ff16801561362d5750600160a060020a0384166000908152600660205260409020600301548d9011155b15613679578388888151811061363f57fe5b600160a060020a03909216602092830290910190910152600190960195613676613669858d614141565b879063ffffffff61475016565b95505b6001909401936135a9565b8615156136945760009950613714565b858c81151561369f57fe5b06925060009150600090505b8282111580156136ba57508681105b156136f8576136ee6136e18983815181106136d157fe5b906020019060200201518d614141565b839063ffffffff61475016565b91506001016136ab565b87600182038151811061370757fe5b9060200190602002015199505b5050505050505050509392505050565b60005433600160a060020a0390811691161461373f57600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f7081604051600160a060020a03909116815260200160405180910390a150565b60008060008060008060006137ba614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156137ff57600080fd5b6102c65a03f1151561381057600080fd5b5050506040518051600160a060020a038b1660009081526005602052604090209097509550508588118015906138495750846006015488115b151561385457600080fd5b8454600686015490945060010192505b8783116138cd5750506002830154600160a060020a0390811660008181526006602090815260408083208684526007019091529020918916146138a682614b0e565b156138c2576138bf6126f183868463ffffffff614b1916565b93505b600190920191613864565b5091979650505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d8681128600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561113957600080fd5b600160a060020a03908116600090815260056020526040902080546001820154600283015460038401546004850154600686015460079096015494979396929092169490939192909190565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156139dd57600080fd5b6102c65a03f115156139ee57600080fd5b5050506040518051159050613a0257600080fd5b613a0a614320565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613a4f57600080fd5b6102c65a03f11515613a6057600080fd5b505050604051805190501515613a7557600080fd5b613a8133611bba614320565b600160a060020a03331660009081526005602052604090209350613aa3614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613ae857600080fd5b6102c65a03f11515613af957600080fd5b5050506040518051600280870154919550889450600160a060020a0390911692509050613b2533610837565b6002811115613b3057fe5b1415613b5157613b4783600163ffffffff61475016565b6004850155613cd5565b6002840154600160a060020a031615801590613b7d57506002840154600160a060020a03868116911614155b15613cd5576000613b8d336134ba565b6001811115613b9857fe5b14613ba257600080fd5b613bb383600163ffffffff61475016565b60048501558354613bcb90839063ffffffff61475016565b8454600160a060020a038316600090815260056020526040902060030154919350613bfc919063ffffffff61455616565b600160a060020a0382166000908152600560205260409020600301556001613c23826134ba565b6001811115613c2e57fe5b1415613cd5576008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6338237efe909183613c648860000154611e4e876138da565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515613cc057600080fd5b6102c65a03f41515613cd157600080fd5b5050505b60008211613ce257600080fd5b60028401805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038716908117909155600090815260056020526040902060030154613d2b9083614750565b600160a060020a0386166000908152600560205260409020600301556001613d52866134ba565b6001811115613d5d57fe5b1415613e1e576002840154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe906008908890613dad908790613da190600160a060020a03166138da565b9063ffffffff61475016565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515613e0957600080fd5b6102c65a03f41515613e1a57600080fd5b5050505b6000861115613ecf578354613e39908763ffffffff61475016565b8455613e43614b6d565b600160a060020a03166323b872dd33613e5a6143b3565b8960006040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b1515613eb357600080fd5b6102c65a03f11515613ec457600080fd5b505050604051805150505b33600160a060020a031681600160a060020a031686600160a060020a03167fe5917769f276ddca9f2ee7c6b0b33e1d1e1b61008010ce622c632dd20d168a2389886000015460405191825260208201526040908101905180910390a4505050505050565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613f7c57600080fd5b6102c65a03f11515613f8d57600080fd5b5050506040518051159050613fa157600080fd5b613fa9614320565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613fee57600080fd5b6102c65a03f11515613fff57600080fd5b50505060405180519050151561401457600080fd5b61402033611bba614320565b600261402b33610837565b600281111561403657fe5b141561404157600080fd5b6118373382614890565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561409457600080fd5b6102c65a03f115156140a557600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156140ce57600080fd5b6002805467ffffffffffffffff191667ffffffffffffffff83161790556000805160206150438339815191526040516020808252600f908201527f756e626f6e64696e67506572696f6400000000000000000000000000000000006040808301919091526060909101905180910390a150565b6000818152600d60209081526040808320600160a060020a038616845260010190915281205460ff16151561417557600080fd5b50600160a060020a0391909116600090815260066020908152604080832093835260079093019052206002015490565b6000806000806000806000806141b9614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156141fe57600080fd5b6102c65a03f1151561420f57600080fd5b5050506040518051600160a060020a038c1660009081526005602052604090209098509650508689118015906142485750856006015489115b151561425357600080fd5b6001808701548754600689015491975095500192505b888311614303576002860154600160a060020a03166000908152600660209081526040808320868452600701909152902091506142a582614b0e565b156142f857506002850154600160a060020a038a81169116146142df6142d283868463ffffffff614bef16565b869063ffffffff61475016565b94506142f56126f183868463ffffffff614b1916565b93505b600190920191614269565b509298975050505050505050565b600054600160a060020a031681565b60008054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156143a257600080fd5b6102c65a03f11515611fec57600080fd5b60008054600160a060020a031663e16c7d986040517f4d696e74657200000000000000000000000000000000000000000000000000008152600601604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156143a257600080fd5b600160a060020a038316600090815260066020908152604080832060058352818420858552600782019093529083209092614476828763ffffffff614c1916565b600383015461448b908763ffffffff61475016565b600384015561449d86613da1896138da565b9050731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6338237efe6008898460008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561451957600080fd5b6102c65a03f4151561345457600080fd5b600061454f620f4240614543858563ffffffff614c9416565b9063ffffffff614cbf16565b9392505050565b60008282111561456257fe5b50900390565b6000614572614320565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156145b757600080fd5b6102c65a03f115156145c857600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a038816845260010190915290205490925060ff161590506146645761462e6146108383614141565b6000838152600d60205260409020600201549063ffffffff61455616565b6000828152600d602090815260408083206002810194909455600160a060020a03861683526001909301905220805460ff191690555b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088460405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b15156146c357600080fd5b6102c65a03f415156146d457600080fd5b50505081600160a060020a03167fc6be59bdc33151833b6dbb6823a9bddecde3c685a1bf4d253d20b4a93fbae56c60405160405180910390a25050565b6000818310614720578161454f565b5090919050565b60028401839055600384019290925560048301556005820155600801805460ff19166001179055565b60008282018381101561475f57fe5b8091505b5092915050565b600160a060020a03808316600090815260056020526040812060028101549092829182918291829182918291161561487d5760045460068901546147b5908b9063ffffffff61455616565b11156147c057600080fd5b87546001808a015460068b015492995097500194505b888511614872576002880154600160a060020a031660009081526006602090815260408083208884526007019091529020935061481284614b0e565b15614867576002880154600160a060020a038b8116911614925061483d84888563ffffffff614cd616565b9092509050614852868363ffffffff61475016565b9550614864878263ffffffff61475016565b96505b6001909401936147d6565b868855600188018690555b5050505060069093019390935550505050565b600160a060020a038216600090815260056020908152604080832084845260088101909252822090916148c38585610806565b15156148ce57600080fd5b50805482546148e3908263ffffffff61475016565b83556002830154600160a060020a0316600090815260056020526040902060030154614915908263ffffffff61475016565b6002840154600160a060020a03166000908152600560205260409020600301556001600284015461494e90600160a060020a03166134ba565b600181111561495957fe5b1415614a0a576002830154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe90600890600160a060020a031661499985613da1836138da565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156149f557600080fd5b6102c65a03f41515614a0657600080fd5b5050505b6000848152600884016020526040808220828155600101919091556002840154600160a060020a03808816929116907f9f5b64cc71e1e26ff178caaa7877a04d8ce66fde989251870e80e6fbee690c1790879085905191825260208201526040908101905180910390a35050505050565b600882015460009060ff1615614ae457614a9982846005015461452a565b6001840154909150614ab1908263ffffffff61475016565b6001840155614ada614ac9838363ffffffff61455616565b60078501549063ffffffff61475016565b6007840155614aff565b6001830154614af9908363ffffffff61475016565b60018401555b505050565b620f424090111590565b600301546000901190565b60088301546000908190819060ff1615614b4257614b38868686614e23565b9092509050614b53565b614b4d868686614e70565b90925090505b614b63828263ffffffff61475016565b9695505050505050565b60008054600160a060020a031663e16c7d986040517f4c69766570656572546f6b656e000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156143a257600080fd5b60088301546000908190819060ff1615614c0e57614b38868686614ee2565b614b4d868686614f2a565b600882015460009060ff1615614c7b57614c3782846004015461452a565b9050614c5a614c4c838363ffffffff61455616565b84549063ffffffff61475016565b83556006830154614c71908263ffffffff61475016565b6006840155614aff565b8254614c8d908363ffffffff61475016565b8355505050565b600080831515614ca75760009150614763565b50828202828482811515614cb757fe5b041461475f57fe5b6000808284811515614ccd57fe5b04949350505050565b6008830154600090819081908190819081908190819060ff1615614d8157614cff8b8b8b614ee2565b9094509250614d14848463ffffffff61475016565b9550614d218b8b8b614e23565b9092509050614d36828263ffffffff61475016565b60018c0154909550614d4e908563ffffffff61455616565b60018c01558a54614d65908363ffffffff61455616565b8b558815614d7c57600060078c0181905560068c01555b614df5565b614d8c8b8b8b614f2a565b9094509250614da1848463ffffffff61475016565b9550614dae8b8b8b614e70565b9092509050614dc3828263ffffffff61475016565b60018c0154909550614ddb908763ffffffff61455616565b60018c01558a54614df2908663ffffffff61455616565b8b555b60038b0154614e0a908b63ffffffff61455616565b6003909b019a909a555092989197509095505050505050565b600080600080866003015411614e3a576000614e4d565b614e4d8660000154868860030154614faa565b905083614e5c57806000614e63565b8086600601545b9250925050935093915050565b600383015460009081908190819081901115614ebf57614e988760000154886004015461452a565b8754909250614ebc90614eb1908463ffffffff61455616565b878960030154614faa565b90505b8415614ed057808293509350614ed8565b925060009150825b5050935093915050565b600080600080866003015411614ef9576000614f0c565b614f0c8660010154868860030154614faa565b905083614f1b57806000614e63565b60079095015494959350505050565b600080600080600080925060009150600088600301541115614f8457614f588860010154896005015461452a565b6001890154909150614f70908263ffffffff61455616565b9250614f8181888a60030154614faa565b91505b8515614f9557818394509450614f9f565b9093506000925083905b505050935093915050565b6000614fcd620f4240614543614fc08686614fd5565b879063ffffffff614c9416565b949350505050565b600061454f8261454385620f424063ffffffff614c9416565b815481835581811511614aff57600083815260209020614aff918101908301615024565b60206040519081016040526000815290565b611ff891905b8082111561503e576000815560010161502a565b509056009f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd674a165627a7a72305820bb4500b0d0f71c5e829d8613a8efbcf5c1f235a626d6d77dcbb0488b355c15590029000000000000000000000000f96d54e490317c557a967abfa5d6e33006be69b3

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

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


   Library Used
SortedDoublyLL : 0x1a0b2cA69ca2C7f96E2529fAA6D63f881655d81A

   Swarm Source:
bzzr://bb4500b0d0f71c5e829d8613a8efbcf5c1f235a626d6d77dcbb0488b355c1559

 

View All
Block Age transaction Difficulty GasUsed Reward
View All
Block Age UncleNumber Difficulty GasUsed Reward
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.