Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
BondingManager
Compiler Version
v0.4.18+commit.9cf6e910
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2018-08-31
*/
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;
// Keep track of total bonded tokens
uint256 private totalBonded;
// Candidate and reserve transcoders
SortedDoublyLL.Data private transcoderPool;
// Represents the active transcoder set
struct ActiveTranscoderSet {
address[] transcoders;
mapping (address => bool) isActive;
uint256 totalStake;
}
// Keep track of active transcoder set for each round
mapping (uint256 => ActiveTranscoderSet) public activeTranscoderSet;
// Check if sender is JobsManager
modifier onlyJobsManager() {
require(msg.sender == controller.getContract(keccak256("JobsManager")));
_;
}
// Check if sender is RoundsManager
modifier onlyRoundsManager() {
require(msg.sender == controller.getContract(keccak256("RoundsManager")));
_;
}
// Check if current round is initialized
modifier currentRoundInitialized() {
require(roundsManager().currentRoundInitialized());
_;
}
// Automatically claim earnings from lastClaimRound through the current round
modifier autoClaimEarnings() {
updateDelegatorWithEarnings(msg.sender, roundsManager().currentRound());
_;
}
/**
* @dev BondingManager constructor. Only invokes constructor of base Manager contract with provided Controller address
* @param _controller Address of Controller that this contract will be registered with
*/
function BondingManager(address _controller) public Manager(_controller) {}
/**
* @dev Set unbonding period. Only callable by Controller owner
* @param _unbondingPeriod Rounds between unbonding and possible withdrawal
*/
function setUnbondingPeriod(uint64 _unbondingPeriod) external onlyControllerOwner {
unbondingPeriod = _unbondingPeriod;
ParameterUpdate("unbondingPeriod");
}
/**
* @dev Set max number of registered transcoders. Only callable by Controller owner
* @param _numTranscoders Max number of registered transcoders
*/
function setNumTranscoders(uint256 _numTranscoders) external onlyControllerOwner {
// Max number of transcoders must be greater than or equal to number of active transcoders
require(_numTranscoders >= numActiveTranscoders);
transcoderPool.setMaxSize(_numTranscoders);
ParameterUpdate("numTranscoders");
}
/**
* @dev Set number of active transcoders. Only callable by Controller owner
* @param _numActiveTranscoders Number of active transcoders
*/
function setNumActiveTranscoders(uint256 _numActiveTranscoders) external onlyControllerOwner {
// Number of active transcoders cannot exceed max number of transcoders
require(_numActiveTranscoders <= transcoderPool.getMaxSize());
numActiveTranscoders = _numActiveTranscoders;
ParameterUpdate("numActiveTranscoders");
}
/**
* @dev Set max number of rounds a caller can claim earnings for at once. Only callable by Controller owner
* @param _maxEarningsClaimsRounds Max number of rounds a caller can claim earnings for at once
*/
function setMaxEarningsClaimsRounds(uint256 _maxEarningsClaimsRounds) external onlyControllerOwner {
maxEarningsClaimsRounds = _maxEarningsClaimsRounds;
ParameterUpdate("maxEarningsClaimsRounds");
}
/**
* @dev The sender is declaring themselves as a candidate for active transcoding.
* @param _rewardCut % of reward paid to transcoder by a delegator
* @param _feeShare % of fees paid to delegators by a transcoder
* @param _pricePerSegment Price per segment (denominated in Wei) for a stream
*/
function transcoder(uint256 _rewardCut, uint256 _feeShare, uint256 _pricePerSegment)
external
whenSystemNotPaused
currentRoundInitialized
{
Transcoder storage t = transcoders[msg.sender];
Delegator storage del = delegators[msg.sender];
if (roundsManager().currentRoundLocked()) {
// If it is the lock period of the current round
// the lowest price previously set by any transcoder
// becomes the price floor and the caller can lower its
// own price to a point greater than or equal to the price floor
// Caller must already be a registered transcoder
require(transcoderStatus(msg.sender) == TranscoderStatus.Registered);
// Provided rewardCut value must equal the current pendingRewardCut value
// This value cannot change during the lock period
require(_rewardCut == t.pendingRewardCut);
// Provided feeShare value must equal the current pendingFeeShare value
// This value cannot change during the lock period
require(_feeShare == t.pendingFeeShare);
// Iterate through the transcoder pool to find the price floor
// Since the caller must be a registered transcoder, the transcoder pool size will always at least be 1
// Thus, we can safely set the initial price floor to be the pendingPricePerSegment of the first
// transcoder in the pool
address currentTranscoder = transcoderPool.getFirst();
uint256 priceFloor = transcoders[currentTranscoder].pendingPricePerSegment;
for (uint256 i = 0; i < transcoderPool.getSize(); i++) {
if (transcoders[currentTranscoder].pendingPricePerSegment < priceFloor) {
priceFloor = transcoders[currentTranscoder].pendingPricePerSegment;
}
currentTranscoder = transcoderPool.getNext(currentTranscoder);
}
// Provided pricePerSegment must be greater than or equal to the price floor and
// less than or equal to the previously set pricePerSegment by the caller
require(_pricePerSegment >= priceFloor && _pricePerSegment <= t.pendingPricePerSegment);
t.pendingPricePerSegment = _pricePerSegment;
TranscoderUpdate(msg.sender, t.pendingRewardCut, t.pendingFeeShare, _pricePerSegment, true);
} else {
// It is not the lock period of the current round
// Caller is free to change rewardCut, feeShare, pricePerSegment as it pleases
// If caller is not a registered transcoder, it can also register and join the transcoder pool
// if it has sufficient delegated stake
// If caller is not a registered transcoder and does not have sufficient delegated stake
// to join the transcoder pool, it can change rewardCut, feeShare, pricePerSegment
// as information signals to delegators in an effort to camapaign and accumulate
// more delegated stake
// Reward cut must be a valid percentage
require(MathUtils.validPerc(_rewardCut));
// Fee share must be a valid percentage
require(MathUtils.validPerc(_feeShare));
// Must have a non-zero amount bonded to self
require(del.delegateAddress == msg.sender && del.bondedAmount > 0);
t.pendingRewardCut = _rewardCut;
t.pendingFeeShare = _feeShare;
t.pendingPricePerSegment = _pricePerSegment;
uint256 delegatedAmount = del.delegatedAmount;
// Check if transcoder is not already registered
if (transcoderStatus(msg.sender) == TranscoderStatus.NotRegistered) {
if (!transcoderPool.isFull()) {
// If pool is not full add new transcoder
transcoderPool.insert(msg.sender, delegatedAmount, address(0), address(0));
} else {
address lastTranscoder = transcoderPool.getLast();
if (delegatedAmount > transcoderPool.getKey(lastTranscoder)) {
// If pool is full and caller has more delegated stake than the transcoder in the pool with the least delegated stake:
// - Evict transcoder in pool with least delegated stake
// - Add caller to pool
transcoderPool.remove(lastTranscoder);
transcoderPool.insert(msg.sender, delegatedAmount, address(0), address(0));
TranscoderEvicted(lastTranscoder);
}
}
}
TranscoderUpdate(msg.sender, _rewardCut, _feeShare, _pricePerSegment, transcoderPool.contains(msg.sender));
}
}
/**
* @dev Delegate stake towards a specific address.
* @param _amount The amount of LPT to stake.
* @param _to The address of the transcoder to stake towards.
*/
function bond(
uint256 _amount,
address _to
)
external
whenSystemNotPaused
currentRoundInitialized
autoClaimEarnings
{
Delegator storage del = delegators[msg.sender];
uint256 currentRound = roundsManager().currentRound();
// Amount to delegate
uint256 delegationAmount = _amount;
// 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, transcoderPool.getKey(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, transcoderPool.getKey(del.delegateAddress).add(delegationAmount), address(0), address(0));
}
if (_amount > 0) {
// Update bonded amount
del.bondedAmount = del.bondedAmount.add(_amount);
// Update total bonded tokens
totalBonded = totalBonded.add(_amount);
// Transfer the LPT to the Minter
livepeerToken().transferFrom(msg.sender, minter(), _amount);
}
Bond(_to, 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);
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);
// Update total bonded tokens
totalBonded = totalBonded.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, transcoderPool.getKey(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(del.delegateAddress, 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 = transcoderPool.getKey(currentTranscoder);
uint256 rewardCut = transcoders[currentTranscoder].pendingRewardCut;
uint256 feeShare = transcoders[currentTranscoder].pendingFeeShare;
uint256 pricePerSegment = transcoders[currentTranscoder].pendingPricePerSegment;
Transcoder storage t = transcoders[currentTranscoder];
// Set pending rates as current rates
t.rewardCut = rewardCut;
t.feeShare = feeShare;
t.pricePerSegment = pricePerSegment;
// Initialize token pool
t.earningsPoolPerRound[currentRound].init(stake, rewardCut, feeShare);
totalStake = totalStake.add(stake);
// Get next transcoder in the pool
currentTranscoder = transcoderPool.getNext(currentTranscoder);
}
// Update total stake of all active transcoders
activeTranscoderSet[currentRound].totalStake = totalStake;
}
/**
* @dev Distribute the token rewards to transcoder and delegates.
* Active transcoders call this once per cycle when it is their turn.
*/
function reward() external whenSystemNotPaused currentRoundInitialized {
uint256 currentRound = roundsManager().currentRound();
// Sender must be an active transcoder
require(activeTranscoderSet[currentRound].isActive[msg.sender]);
// Transcoder must not have called reward for this round already
require(transcoders[msg.sender].lastRewardRound != currentRound);
// Set last round that transcoder called reward
transcoders[msg.sender].lastRewardRound = currentRound;
// Create reward based on active transcoder's stake relative to the total active stake
// rewardTokens = (current mintable tokens for the round * active transcoder stake) / total active stake
uint256 rewardTokens = minter().createReward(activeTranscoderTotalStake(msg.sender, currentRound), activeTranscoderSet[currentRound].totalStake);
updateTranscoderWithRewards(msg.sender, rewardTokens, currentRound);
Reward(msg.sender, rewardTokens);
}
/**
* @dev Update transcoder's fee pool
* @param _transcoder Transcoder address
* @param _fees Fees from verified job claims
*/
function updateTranscoderWithFees(
address _transcoder,
uint256 _fees,
uint256 _round
)
external
whenSystemNotPaused
onlyJobsManager
{
// Transcoder must be registered
require(transcoderStatus(_transcoder) == TranscoderStatus.Registered);
Transcoder storage t = transcoders[_transcoder];
EarningsPool.Data storage earningsPool = t.earningsPoolPerRound[_round];
// Add fees to fee pool
earningsPool.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);
totalBonded = totalBonded.sub(penalty);
}
// If registered transcoder, resign it
if (transcoderStatus(_transcoder) == TranscoderStatus.Registered) {
resignTranscoder(_transcoder);
}
// Account for penalty
uint256 burnAmount = penalty;
// Award finder fee if there is a finder address
if (_finder != address(0)) {
uint256 finderAmount = MathUtils.percOf(penalty, _finderFee);
minter().trustedTransferTokens(_finder, finderAmount);
// Minter burns the slashed funds - finder reward
minter().trustedBurnTokens(burnAmount.sub(finderAmount));
TranscoderSlashed(_transcoder, _finder, penalty, finderAmount);
} else {
// Minter burns the slashed funds
minter().trustedBurnTokens(burnAmount);
TranscoderSlashed(_transcoder, address(0), penalty, 0);
}
} else {
TranscoderSlashed(_transcoder, _finder, 0, 0);
}
}
/**
* @dev Pseudorandomly elect a currently active transcoder that charges a price per segment less than or equal to the max price per segment for a job
* Returns address of elected active transcoder and its price per segment
* @param _maxPricePerSegment Max price (in LPT base units) per segment of a stream
* @param _blockHash Job creation block hash used as a pseudorandom seed for assigning an active transcoder
* @param _round Job creation round
*/
function electActiveTranscoder(uint256 _maxPricePerSegment, bytes32 _blockHash, uint256 _round) external view returns (address) {
uint256 activeSetSize = activeTranscoderSet[_round].transcoders.length;
// Create array to store available transcoders charging an acceptable price per segment
address[] memory availableTranscoders = new address[](activeSetSize);
// Keep track of the actual number of available transcoders
uint256 numAvailableTranscoders = 0;
// Keep track of total stake of available transcoders
uint256 totalAvailableTranscoderStake = 0;
for (uint256 i = 0; i < activeSetSize; i++) {
address activeTranscoder = activeTranscoderSet[_round].transcoders[i];
// If a transcoder is active and charges an acceptable price per segment add it to the array of available transcoders
if (activeTranscoderSet[_round].isActive[activeTranscoder] && transcoders[activeTranscoder].pricePerSegment <= _maxPricePerSegment) {
availableTranscoders[numAvailableTranscoders] = activeTranscoder;
numAvailableTranscoders++;
totalAvailableTranscoderStake = totalAvailableTranscoderStake.add(activeTranscoderTotalStake(activeTranscoder, _round));
}
}
if (numAvailableTranscoders == 0) {
// There is no currently available transcoder that charges a price per segment less than or equal to the max price per segment for a job
return address(0);
} else {
// Pseudorandomly pick an available transcoder weighted by its stake relative to the total stake of all available transcoders
uint256 r = uint256(_blockHash) % totalAvailableTranscoderStake;
uint256 s = 0;
uint256 j = 0;
while (s <= r && j < numAvailableTranscoders) {
s = s.add(activeTranscoderTotalStake(availableTranscoders[j], _round));
j++;
}
return availableTranscoders[j - 1];
}
}
/**
* @dev Claim token pools shares for a delegator from its lastClaimRound through the end round
* @param _endRound The last round for which to claim token pools shares for a delegator
*/
function claimEarnings(uint256 _endRound) external whenSystemNotPaused currentRoundInitialized {
// End round must be after the last claim round
require(delegators[msg.sender].lastClaimRound < _endRound);
// End round must not be after the current round
require(_endRound <= roundsManager().currentRound());
updateDelegatorWithEarnings(msg.sender, _endRound);
}
/**
* @dev Returns pending bonded stake for a delegator from its lastClaimRound through an end round
* @param _delegator Address of delegator
* @param _endRound The last round to compute pending stake from
*/
function pendingStake(address _delegator, uint256 _endRound) public view returns (uint256) {
uint256 currentRound = roundsManager().currentRound();
Delegator storage del = delegators[_delegator];
// End round must be before or equal to current round and after lastClaimRound
require(_endRound <= currentRound && _endRound > del.lastClaimRound);
uint256 currentBondedAmount = del.bondedAmount;
for (uint256 i = del.lastClaimRound + 1; i <= _endRound; i++) {
EarningsPool.Data storage earningsPool = transcoders[del.delegateAddress].earningsPoolPerRound[i];
bool isTranscoder = _delegator == del.delegateAddress;
if (earningsPool.hasClaimableShares()) {
// Calculate and add reward pool share from this round
currentBondedAmount = currentBondedAmount.add(earningsPool.rewardPoolShare(currentBondedAmount, isTranscoder));
}
}
return currentBondedAmount;
}
/**
* @dev Returns pending fees for a delegator from its lastClaimRound through an end round
* @param _delegator Address of delegator
* @param _endRound The last round to compute pending fees from
*/
function pendingFees(address _delegator, uint256 _endRound) public view returns (uint256) {
uint256 currentRound = roundsManager().currentRound();
Delegator storage del = delegators[_delegator];
// End round must be before or equal to current round and after lastClaimRound
require(_endRound <= currentRound && _endRound > del.lastClaimRound);
uint256 currentFees = del.fees;
uint256 currentBondedAmount = del.bondedAmount;
for (uint256 i = del.lastClaimRound + 1; i <= _endRound; i++) {
EarningsPool.Data storage earningsPool = transcoders[del.delegateAddress].earningsPoolPerRound[i];
if (earningsPool.hasClaimableShares()) {
bool isTranscoder = _delegator == del.delegateAddress;
// Calculate and add fee pool share from this round
currentFees = currentFees.add(earningsPool.feePoolShare(currentBondedAmount, isTranscoder));
// Calculate new bonded amount with rewards from this round. Updated bonded amount used
// to calculate fee pool share in next round
currentBondedAmount = currentBondedAmount.add(earningsPool.rewardPoolShare(currentBondedAmount, isTranscoder));
}
}
return currentFees;
}
/**
* @dev Returns total bonded stake for an active transcoder
* @param _transcoder Address of a transcoder
*/
function activeTranscoderTotalStake(address _transcoder, uint256 _round) public view returns (uint256) {
// Must be active transcoder
require(activeTranscoderSet[_round].isActive[_transcoder]);
return transcoders[_transcoder].earningsPoolPerRound[_round].totalStake;
}
/**
* @dev Returns total bonded stake for a transcoder
* @param _transcoder Address of transcoder
*/
function transcoderTotalStake(address _transcoder) public view returns (uint256) {
return transcoderPool.getKey(_transcoder);
}
/*
* @dev Computes transcoder status
* @param _transcoder Address of transcoder
*/
function transcoderStatus(address _transcoder) public view returns (TranscoderStatus) {
if (transcoderPool.contains(_transcoder)) {
return TranscoderStatus.Registered;
} else {
return TranscoderStatus.NotRegistered;
}
}
/**
* @dev Computes delegator status
* @param _delegator Address of delegator
*/
function delegatorStatus(address _delegator) public view returns (DelegatorStatus) {
Delegator storage del = delegators[_delegator];
if (del.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) {
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 = transcoderPool.getKey(_transcoder).add(_rewards);
transcoderPool.updateKey(_transcoder, newStake, address(0), address(0));
// Update total bonded tokens with claimable rewards
totalBonded = totalBonded.add(_rewards);
}
/**
* @dev Update a delegator with token pools shares from its lastClaimRound through a given round
* @param _delegator Delegator address
* @param _endRound The last round for which to update a delegator's stake with token pools shares
*/
function updateDelegatorWithEarnings(address _delegator, uint256 _endRound) internal {
Delegator storage del = delegators[_delegator];
// Only will have earnings to claim if you have a delegate
// If not delegated, skip the earnings claim process
if (del.delegateAddress != address(0)) {
// Cannot claim earnings for more than maxEarningsClaimsRounds
// This is a number to cause transactions to fail early if
// we know they will require too much gas to loop through all the necessary rounds to claim earnings
// The user should instead manually invoke `claimEarnings` to split up the claiming process
// across multiple transactions
require(_endRound.sub(del.lastClaimRound) <= maxEarningsClaimsRounds);
uint256 currentBondedAmount = del.bondedAmount;
uint256 currentFees = del.fees;
for (uint256 i = del.lastClaimRound + 1; i <= _endRound; i++) {
EarningsPool.Data storage earningsPool = transcoders[del.delegateAddress].earningsPoolPerRound[i];
if (earningsPool.hasClaimableShares()) {
bool isTranscoder = _delegator == del.delegateAddress;
var (fees, rewards) = earningsPool.claimShare(currentBondedAmount, isTranscoder);
currentFees = currentFees.add(fees);
currentBondedAmount = currentBondedAmount.add(rewards);
}
}
// Rewards are bonded by default
del.bondedAmount = currentBondedAmount;
del.fees = currentFees;
}
del.lastClaimRound = _endRound;
}
/**
* @dev 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);
// Update total bonded tokens
totalBonded = totalBonded.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, transcoderPool.getKey(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 Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"constant":true,"inputs":[],"name":"maxEarningsClaimsRounds","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_delegator","type":"address"},{"name":"_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
6060604052341561000f57600080fd5b60405160208061524b8339810160405280805160008054600160a060020a03909216600160a060020a031990921691909117905550506151f7806100546000396000f3006060604052600436106101f55763ffffffff60e060020a600035041663038424c381146101fa5780630fd02fc11461021f5780631544fc6714610255578063228cb7331461029857806322bf9d7c146102ad578063235c9603146102d8578063242ed69f1461031357806324454fc41461032657806324b1babf1461039557806325d5971f146103ab57806327de9e32146103c15780632a4e0d55146103d75780633a080e93146103ea5780633aeb512c1461040c5780633da1c2f514610431578063412f83b614610447578063476343ee1461048157806351720b41146104945780635a2a75a9146104a75780635c50c356146104ba5780635dce9948146104cd57806360c79d001461052a57806361e25d2314610540578063673a456b1461055357806368ba170c146105695780636cf6d6751461058857806372d9f13d146105b857806377517765146105ce5780637c0207cb146105e457806385aaff621461060657806388a6c749146106225780638b2f16521461063557806391fdf6b11461066457806392eefe9b146106805780639d0b2c7a1461069f5780639ef9df94146106c1578063a64ad595146106e0578063b78d27dc14610751578063eaffb3f914610773578063f10d1de114610789578063f2083220146107a9578063f595f1cc146107cb578063f77c4791146107ed575b600080fd5b341561020557600080fd5b61020d610800565b60405190815260200160405180910390f35b341561022a57600080fd5b610241600160a060020a0360043516602435610806565b604051901515815260200160405180910390f35b341561026057600080fd5b610274600160a060020a0360043516610837565b6040518082600281111561028457fe5b60ff16815260200191505060405180910390f35b34156102a357600080fd5b6102ab610974565b005b34156102b857600080fd5b6102ab600160a060020a0360043581169060243516604435606435610c13565b34156102e357600080fd5b6102f7600160a060020a03600435166110e6565b604051600160a060020a03909116815260200160405180910390f35b341561031e57600080fd5b6102ab611171565b341561033157600080fd5b610348600160a060020a03600435166024356116da565b60405198895260208901979097526040808901969096526060880194909452608087019290925260a086015260c085015260e0840152901515610100830152610120909101905180910390f35b34156103a057600080fd5b6102ab600435611741565b34156103b657600080fd5b6102ab6004356118cb565b34156103cc57600080fd5b6102ab600435611b57565b34156103e257600080fd5b61020d612078565b34156103f557600080fd5b6102ab600160a060020a03600435166024356120f2565b341561041757600080fd5b6102ab600160a060020a03600435166024356044356122d0565b341561043c57600080fd5b61020d60043561245b565b341561045257600080fd5b610469600160a060020a0360043516602435612470565b60405191825260208201526040908101905180910390f35b341561048c57600080fd5b6102ab6124a4565b341561049f57600080fd5b61020d61267f565b34156104b257600080fd5b61020d612685565b34156104c557600080fd5b61020d6126df565b34156104d857600080fd5b6104ec600160a060020a03600435166126e5565b60405196875260208701959095526040808701949094526060860192909252608085015260a084015260c083019190915260e0909101905180910390f35b341561053557600080fd5b6102ab60043561272e565b341561054b57600080fd5b61020d612880565b341561055e57600080fd5b6102ab600435612886565b341561057457600080fd5b610241600160a060020a03600435166129e4565b341561059357600080fd5b61059b612a03565b60405167ffffffffffffffff909116815260200160405180910390f35b34156105c357600080fd5b6102ab600435612a13565b34156105d957600080fd5b61020d600435612af1565b34156105ef57600080fd5b610241600160a060020a0360043516602435612b06565b341561061157600080fd5b6102ab600435602435604435612b34565b341561062d57600080fd5b6102f761342a565b341561064057600080fd5b610654600160a060020a0360043516613484565b6040518082600181111561028457fe5b341561066f57600080fd5b6102f760043560243560443561351d565b341561068b57600080fd5b6102ab600160a060020a03600435166136ee565b34156106aa57600080fd5b61020d600160a060020a0360043516602435613771565b34156106cc57600080fd5b61020d600160a060020a03600435166138b1565b34156106eb57600080fd5b6106ff600160a060020a036004351661391a565b6040518088815260200187815260200186600160a060020a0316600160a060020a0316815260200185815260200184815260200183815260200182815260200197505050505050505060405180910390f35b341561075c57600080fd5b6102ab600435600160a060020a0360243516613966565b341561077e57600080fd5b6102ab600435613fbb565b341561079457600080fd5b6102ab67ffffffffffffffff600435166140d3565b34156107b457600080fd5b61020d600160a060020a03600435166024356141c9565b34156107d657600080fd5b61020d600160a060020a036004351660243561422d565b34156107f857600080fd5b6102f7614399565b60045481565b600160a060020a03821660009081526005602090815260408083208484526008019091528120600101541192915050565b600160a060020a038116600090815260056020526040812080541515610860576002915061096e565b6108686143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156108ad57600080fd5b6102c65a03f115156108be57600080fd5b50505060405180519050816004015411156108dc576000915061096e565b6000816004015411801561095b57506108f36143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561093857600080fd5b6102c65a03f1151561094957600080fd5b50505060405180519050816004015411155b15610969576001915061096e565b600291505b50919050565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156109be57600080fd5b6102c65a03f115156109cf57600080fd5b50505060405180511590506109e357600080fd5b6109eb6143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610a3057600080fd5b6102c65a03f11515610a4157600080fd5b505050604051805190501515610a5657600080fd5b610a5e6143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610aa357600080fd5b6102c65a03f11515610ab457600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a033316845260010190915290205490935060ff1615159050610af557600080fd5b600160a060020a033316600090815260066020526040902054821415610b1a57600080fd5b600160a060020a0333166000908152600660205260409020829055610b3d61443b565b600160a060020a0316637dbedad5610b5533856141c9565b6000858152600d6020526040808220600201549190516020015260405160e060020a63ffffffff851602815260048101929092526024820152604401602060405180830381600087803b1515610baa57600080fd5b6102c65a03f11515610bbb57600080fd5b505050604051805190509050610bd23382846144bd565b33600160a060020a03167f619caafabdd75649b302ba8419e48cccf64f37f1983ac4727cfb38b57703ffc98260405190815260200160405180910390a25050565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610c6157600080fd5b6102c65a03f11515610c7257600080fd5b5050506040518051159050610c8657600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610d0757600080fd5b6102c65a03f11515610d1857600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515610d4157600080fd5b600160a060020a03881660009081526005602052604081208054909550111561107757600160a060020a038816600090815260056020526040902054610d879087614633565b8454909350610d9c908463ffffffff61465f16565b84556001610da989610837565b6002811115610db457fe5b1415610e21576002840154600160a060020a0316600090815260056020526040902060030154610dea908463ffffffff61465f16565b6002850154600160a060020a0316600090815260056020526040902060030155600754610e1d908463ffffffff61465f16565b6007555b6001610e2c89613484565b6001811115610e3757fe5b1415610e4657610e4688614671565b829150600160a060020a03871615610fab57610e628386614633565b9050610e6c61443b565b600160a060020a031663e7a49c2b888360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515610ebf57600080fd5b6102c65a03f11515610ed057600080fd5b505050610edb61443b565b600160a060020a031663c7ee98c2610ef9848463ffffffff61465f16565b60405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610f2f57600080fd5b6102c65a03f11515610f4057600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c228885846040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a2611072565b610fb361443b565b600160a060020a031663c7ee98c28360405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610ff857600080fd5b6102c65a03f1151561100957600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c2260008560006040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b6110dc565b87600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c22886000806040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b5050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561114f57600080fd5b6102c65a03f4151561116057600080fd5b50505060405180519150505b919050565b6000806000806000806000806000806000809054906101000a9004600160a060020a0316600160a060020a0316635c975abb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156111da57600080fd5b6102c65a03f115156111eb57600080fd5b50505060405180511590506111ff57600080fd5b600054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561128057600080fd5b6102c65a03f1151561129157600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156112ba57600080fd5b6112c26143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561130757600080fd5b6102c65a03f1151561131857600080fd5b5050506040518051600354909b506113a49150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561138457600080fd5b6102c65a03f4151561139557600080fd5b5050506040518051905061481a565b985060009750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed60088a6040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561140257600080fd5b6102c65a03f4151561141357600080fd5b5050506040518051975060009650505b888610156116ba5760008a8152600d602052604090208054600181016114498382615157565b506000918252602080832091909101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038b169081179091558c8352600d825260408084209184526001918201909252818320805460ff19169091179055731a0b2ca69ca2c7f96e2529faa6d63f881655d81a9163d8681128916008918b91516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561150e57600080fd5b6102c65a03f4151561151f57600080fd5b5050506040518051905094506006600088600160a060020a0316600160a060020a031681526020019081526020016000206004015493506006600088600160a060020a0316600160a060020a031681526020019081526020016000206005015492506006600088600160a060020a0316600160a060020a031681526020019081526020016000206006015491506006600088600160a060020a0316600160a060020a0316815260200190815260200160002090508381600101819055508281600201819055508181600301819055506116198585858460070160008f8152602001908152602001600020614830909392919063ffffffff16565b611629888663ffffffff61485916565b9750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088960006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561169357600080fd5b6102c65a03f415156116a457600080fd5b5050506040518051975050600190950194611423565b50505060009687525050600d602052505060409092206002019190915550565b600160a060020a03909116600090815260066020818152604080842094845260079485019091529091208054600182015460028301546003840154600485015460058601549686015497860154600890960154949893979296919590949193909160ff1690565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561178a57600080fd5b6102c65a03f1151561179b57600080fd5b50505060405180511590506117af57600080fd5b6117b76143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156117fc57600080fd5b6102c65a03f1151561180d57600080fd5b50505060405180519050151561182257600080fd5b600160a060020a03331660009081526005602052604090206006015481901061184a57600080fd5b6118526143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561189757600080fd5b6102c65a03f115156118a857600080fd5b505050604051805182111590506118be57600080fd5b6118c83382614873565b50565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561191957600080fd5b6102c65a03f1151561192a57600080fd5b505050604051805115905061193e57600080fd5b6119466143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561198b57600080fd5b6102c65a03f1151561199c57600080fd5b5050506040518051905015156119b157600080fd5b33600160a060020a03811660009081526005602090815260408083208984526008810190925290912090955093506119e99086610806565b15156119f457600080fd5b6119fc6143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611a4157600080fd5b6102c65a03f11515611a5257600080fd5b5050506040518051600185015411159050611a6c57600080fd5b505080546001808301546000868152600886016020526040812081815590920191909155611a9861443b565b600160a060020a031663e7a49c2b338460405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515611aeb57600080fd5b6102c65a03f11515611afc57600080fd5b50505033600160a060020a03167f1340f1a8f3d456a649e1a12071dfa15655e3d09252131d0f980c3b405cc8dd2e86848460405180848152602001838152602001828152602001935050505060405180910390a25050505050565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611ba557600080fd5b6102c65a03f11515611bb657600080fd5b5050506040518051159050611bca57600080fd5b611bd26143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611c1757600080fd5b6102c65a03f11515611c2857600080fd5b505050604051805190501515611c3d57600080fd5b611cae33611c496143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611c8e57600080fd5b6102c65a03f11515611c9f57600080fd5b50505060405180519050614873565b6001611cb933610837565b6002811115611cc457fe5b14611cce57600080fd5b600160a060020a033316600090815260056020526040812094508511611cf357600080fd5b8354851115611d0157600080fd5b611d096143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611d4e57600080fd5b6102c65a03f11515611d5f57600080fd5b5050506040518051600254909450611d899150849067ffffffffffffffff1663ffffffff61485916565b915083600701549050604080519081016040908152868252602080830185905260008481526008880190915220815181556020820151600191820155611dd79150829063ffffffff61485916565b60078501558354611dee908663ffffffff61465f16565b84556002840154600160a060020a0316600090815260056020526040902060030154611e20908663ffffffff61465f16565b6002850154600160a060020a0316600090815260056020526040902060030155600754611e53908663ffffffff61465f16565b60075560016002850154611e6f90600160a060020a0316613484565b6001811115611e7a57fe5b148015611ea45750600284015433600160a060020a039081169116141580611ea457508354600090115b15611fc5576002840154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe90600890600160a060020a0316611f54898563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515611f2d57600080fd5b6102c65a03f41515611f3e57600080fd5b505050604051805191905063ffffffff61465f16565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515611fb057600080fd5b6102c65a03f41515611fc157600080fd5b5050505b835415156120185760028401805473ffffffffffffffffffffffffffffffffffffffff19169055600060048501556001611ffe33613484565b600181111561200957fe5b14156120185761201833614671565b6002840154600160a060020a0333811691167f2d5d98d189bee5496a08db2a5948cb7e5e786f09d17d0c3f228eb41776c24a0683888660405180848152602001838152602001828152602001935050505060405180910390a35050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece586008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156120d257600080fd5b6102c65a03f415156120e357600080fd5b50505060405180519150505b90565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561213b57600080fd5b6102c65a03f1151561214c57600080fd5b505050604051805115905061216057600080fd5b6121686143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156121ad57600080fd5b6102c65a03f115156121be57600080fd5b5050506040518051905015156121d357600080fd5b6121df33611c496143a8565b60026121ea33610837565b60028111156121f557fe5b146121ff57600080fd5b612278600161220c6143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561225157600080fd5b6102c65a03f1151561226257600080fd5b505050604051805191905063ffffffff61485916565b33600160a060020a03818116600090815260056020526040902060048101939093556002909201805473ffffffffffffffffffffffffffffffffffffffff1916928516929092179091556122cc9082614999565b5050565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561231a57600080fd5b6102c65a03f1151561232b57600080fd5b505050604051805115905061233f57600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156123c057600080fd5b6102c65a03f115156123d157600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156123fa57600080fd5b600161240586613484565b600181111561241057fe5b1461241a57600080fd5b5050600160a060020a038316600090815260066020908152604080832084845260078101909252909120612454818563ffffffff614be416565b5050505050565b600d6020526000908152604090206002015481565b600160a060020a03919091166000908152600560209081526040808320938352600890930190522080546001909101549091565b60008054600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156124ec57600080fd5b6102c65a03f115156124fd57600080fd5b505050604051805115905061251157600080fd5b6125196143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561255e57600080fd5b6102c65a03f1151561256f57600080fd5b50505060405180519050151561258457600080fd5b61259033611c496143a8565b600160a060020a033316600090815260056020526040812060010154116125b657600080fd5b50600160a060020a033316600090815260056020526040812060010180549190556125df61443b565b600160a060020a03166320283da9338360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b151561263257600080fd5b6102c65a03f1151561264357600080fd5b50505033600160a060020a03167fd3719f04262b628e1d01a6ed24707f542cda51f144b5271149c7d0419436d00c60405160405180910390a250565b60015481565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156120d257600080fd5b60075490565b600160a060020a03166000908152600660208190526040909120805460018201546002830154600384015460048501546005860154959096015493969295919490939192909190565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561277757600080fd5b6102c65a03f1151561278857600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156127b157600080fd5b6003548110156127c057600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63a176adaf60088360405160e060020a63ffffffff85160281526004810192909252602482015260440160006040518083038186803b151561281657600080fd5b6102c65a03f4151561282757600080fd5b5050506000805160206151ac8339815191526040516020808252600e908201527f6e756d5472616e73636f646572730000000000000000000000000000000000006040808301919091526060909101905180910390a150565b60035481565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156128cf57600080fd5b6102c65a03f115156128e057600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561290957600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561296257600080fd5b6102c65a03f4151561297357600080fd5b5050506040518051821115905061298957600080fd5b60038190556000805160206151ac83398151915260405160208082526014908201527f6e756d4163746976655472616e73636f646572730000000000000000000000006040808301919091526060909101905180910390a150565b600060016129f183613484565b60018111156129fc57fe5b1492915050565b60025467ffffffffffffffff1681565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612a5c57600080fd5b6102c65a03f11515612a6d57600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515612a9657600080fd5b60048190556000805160206151ac83398151915260405160208082526017908201527f6d61784561726e696e6773436c61696d73526f756e64730000000000000000006040808301919091526060909101905180910390a150565b6000908152600d602052604090206002015490565b6000908152600d60209081526040808320600160a060020a0394909416835260019093019052205460ff1690565b60008054819081908190819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612b8857600080fd5b6102c65a03f11515612b9957600080fd5b5050506040518051159050612bad57600080fd5b612bb56143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612bfa57600080fd5b6102c65a03f11515612c0b57600080fd5b505050604051805190501515612c2057600080fd5b600160a060020a033316600090815260066020908152604080832060059092529091209097509550612c506143a8565b600160a060020a0316636841f2536000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612c9557600080fd5b6102c65a03f11515612ca657600080fd5b5050506040518051905015612f6c576001612cc033613484565b6001811115612ccb57fe5b14612cd557600080fd5b60048701548a14612ce557600080fd5b60058701548914612cf557600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612d4e57600080fd5b6102c65a03f41515612d5f57600080fd5b5050506040518051600160a060020a0381166000908152600660208190526040822001549197509095509350505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612de657600080fd5b6102c65a03f41515612df757600080fd5b50505060405180519050831015612edc57600160a060020a0385166000908152600660208190526040909120015484901015612e4d57600160a060020a0385166000908152600660208190526040909120015493505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088760006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612eb557600080fd5b6102c65a03f41515612ec657600080fd5b5050506040518051955050600190920191612d8d565b838810158015612ef0575086600601548811155b1515612efb57600080fd5b87876006018190555033600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be7886004015489600501548b6001604051938452602084019290925260408084019190915290151560608301526080909101905180910390a261341e565b612f758a614c6d565b1515612f8057600080fd5b612f8989614c6d565b1515612f9457600080fd5b600286015433600160a060020a039081169116148015612fb657508554600090115b1515612fc157600080fd5b600487018a90556005870189905560068701889055600386015491506000612fe833613484565b6001811115612ff357fe5b141561333f57731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634aa12990600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561305257600080fd5b6102c65a03f4151561306357600080fd5b50505060405180519050151561310657731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a66008338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156130ed57600080fd5b6102c65a03f415156130fe57600080fd5b50505061333f565b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6372e40b26600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561315f57600080fd5b6102c65a03f4151561317057600080fd5b50505060405180519150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a905063d868112860088360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156131e457600080fd5b6102c65a03f415156131f557600080fd5b5050506040518051905082111561333f57731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088360405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b151561326557600080fd5b6102c65a03f4151561327657600080fd5b5050506008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a69091338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156132f557600080fd5b6102c65a03f4151561330657600080fd5b50505080600160a060020a03167e05588101bf85a737dacb8be2233b33113aaa5c5743525cfbfe2f6a77c2f6ff60405160405180910390a25b33600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be78b8b8b6008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c4790913360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156133d757600080fd5b6102c65a03f415156133e857600080fd5b50505060405180519050604051938452602084019290925260408084019190915290151560608301526080909101905180910390a25b50505050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156120d257600080fd5b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c47600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156134ed57600080fd5b6102c65a03f415156134fe57600080fd5b50505060405180519050156135155750600161116c565b50600061116c565b60008061352861517b565b6000848152600d60205260408082205493508190819081908190819081908990518059106135535750595b908082528060200260200182016040525097506000965060009550600094505b8885101561364e5760008b8152600d6020526040902080548690811061359557fe5b60009182526020808320909101548d8352600d82526040808420600160a060020a0390921680855260019290920190925291205490945060ff1680156135f75750600160a060020a0384166000908152600660205260409020600301548d9011155b15613643578388888151811061360957fe5b600160a060020a03909216602092830290910190910152600190960195613640613633858d6141c9565b879063ffffffff61485916565b95505b600190940193613573565b86151561365e57600099506136de565b858c81151561366957fe5b06925060009150600090505b82821115801561368457508681105b156136c2576136b86136ab89838151811061369b57fe5b906020019060200201518d6141c9565b839063ffffffff61485916565b9150600101613675565b8760018203815181106136d157fe5b9060200190602002015199505b5050505050505050509392505050565b60005433600160a060020a0390811691161461370957600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f7081604051600160a060020a03909116815260200160405180910390a150565b60008060008060008060006137846143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156137c957600080fd5b6102c65a03f115156137da57600080fd5b5050506040518051600160a060020a038b1660009081526005602052604090209097509550508588118015906138135750846006015488115b151561381e57600080fd5b8454600686015490945060010192505b8783116138a45750506002830154600160a060020a03908116600081815260066020908152604080832086845260070190915290209189161461387082614c77565b156138995761389661388983868463ffffffff614c8216565b859063ffffffff61485916565b93505b60019092019161382e565b5091979650505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d8681128600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561114f57600080fd5b600160a060020a03908116600090815260056020526040902080546001820154600283015460038401546004850154600686015460079096015494979396929092169490939192909190565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156139b457600080fd5b6102c65a03f115156139c557600080fd5b50505060405180511590506139d957600080fd5b6139e16143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613a2657600080fd5b6102c65a03f11515613a3757600080fd5b505050604051805190501515613a4c57600080fd5b613a5833611c496143a8565b600160a060020a03331660009081526005602052604090209350613a7a6143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613abf57600080fd5b6102c65a03f11515613ad057600080fd5b5050506040518051600280870154919550889450600160a060020a0390911692509050613afc33610837565b6002811115613b0757fe5b1415613b2857613b1e83600163ffffffff61485916565b6004850155613cf6565b6002840154600160a060020a031615801590613b5457506002840154600160a060020a03868116911614155b15613cf6576000613b6433613484565b6001811115613b6f57fe5b14613b7957600080fd5b613b8a83600163ffffffff61485916565b60048501558354613ba290839063ffffffff61485916565b8454600160a060020a038316600090815260056020526040902060030154919350613bd3919063ffffffff61465f16565b600160a060020a0382166000908152600560205260409020600301556001613bfa82613484565b6001811115613c0557fe5b1415613cf6578354731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe906008908490613c85908563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515611f2d57600080fd5b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515613ce157600080fd5b6102c65a03f41515613cf257600080fd5b5050505b60008211613d0357600080fd5b60028401805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038716908117909155600090815260056020526040902060030154613d4c9083614859565b600160a060020a0386166000908152600560205260409020600301556001613d7386613484565b6001811115613d7e57fe5b1415613e90576002840154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe906008908890613e1f908790869063d8681128908690600160a060020a031660006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515613e0e57600080fd5b6102c65a03f4151561226257600080fd5b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515613e7b57600080fd5b6102c65a03f41515613e8c57600080fd5b5050505b6000861115613f57578354613eab908763ffffffff61485916565b8455600754613ec0908763ffffffff61485916565b600755613ecb614cd6565b600160a060020a03166323b872dd33613ee261443b565b8960006040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b1515613f3b57600080fd5b6102c65a03f11515613f4c57600080fd5b505050604051805150505b33600160a060020a031681600160a060020a031686600160a060020a03167fe5917769f276ddca9f2ee7c6b0b33e1d1e1b61008010ce622c632dd20d168a2389886000015460405191825260208201526040908101905180910390a4505050505050565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561400457600080fd5b6102c65a03f1151561401557600080fd5b505050604051805115905061402957600080fd5b6140316143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561407657600080fd5b6102c65a03f1151561408757600080fd5b50505060405180519050151561409c57600080fd5b6140a833611c496143a8565b60026140b333610837565b60028111156140be57fe5b14156140c957600080fd5b6118c83382614999565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561411c57600080fd5b6102c65a03f1151561412d57600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561415657600080fd5b6002805467ffffffffffffffff191667ffffffffffffffff83161790556000805160206151ac8339815191526040516020808252600f908201527f756e626f6e64696e67506572696f6400000000000000000000000000000000006040808301919091526060909101905180910390a150565b6000818152600d60209081526040808320600160a060020a038616845260010190915281205460ff1615156141fd57600080fd5b50600160a060020a0391909116600090815260066020908152604080832093835260079093019052206002015490565b6000806000806000806000806142416143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561428657600080fd5b6102c65a03f1151561429757600080fd5b5050506040518051600160a060020a038c1660009081526005602052604090209098509650508689118015906142d05750856006015489115b15156142db57600080fd5b6001808701548754600689015491975095500192505b88831161438b576002860154600160a060020a031660009081526006602090815260408083208684526007019091529020915061432d82614c77565b1561438057506002850154600160a060020a038a811691161461436761435a83868463ffffffff614d5816565b869063ffffffff61485916565b945061437d61388983868463ffffffff614c8216565b93505b6001909201916142f1565b509298975050505050505050565b600054600160a060020a031681565b60008054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561442a57600080fd5b6102c65a03f115156120e357600080fd5b60008054600160a060020a031663e16c7d986040517f4d696e74657200000000000000000000000000000000000000000000000000008152600601604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561442a57600080fd5b600160a060020a0383166000908152600660209081526040808320600583528184208585526007820190935290832090926144fe828763ffffffff614d8216565b6003830154614513908763ffffffff61485916565b600384015561458486731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d868112860088b60006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515613e0e57600080fd5b9050731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6338237efe6008898460008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561460057600080fd5b6102c65a03f4151561461157600080fd5b505060075461462791508763ffffffff61485916565b60075550505050505050565b6000614658620f424061464c858563ffffffff614dfd16565b9063ffffffff614e2816565b9392505050565b60008282111561466b57fe5b50900390565b600061467b6143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156146c057600080fd5b6102c65a03f115156146d157600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a038816845260010190915290205490925060ff1615905061476d5761473761471983836141c9565b6000838152600d60205260409020600201549063ffffffff61465f16565b6000828152600d602090815260408083206002810194909455600160a060020a03861683526001909301905220805460ff191690555b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088460405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b15156147cc57600080fd5b6102c65a03f415156147dd57600080fd5b50505081600160a060020a03167fc6be59bdc33151833b6dbb6823a9bddecde3c685a1bf4d253d20b4a93fbae56c60405160405180910390a25050565b60008183106148295781614658565b5090919050565b60028401839055600384019290925560048301556005820155600801805460ff19166001179055565b60008282018381101561486857fe5b8091505b5092915050565b600160a060020a0380831660009081526005602052604081206002810154909282918291829182918291829116156149865760045460068901546148be908b9063ffffffff61465f16565b11156148c957600080fd5b87546001808a015460068b015492995097500194505b88851161497b576002880154600160a060020a031660009081526006602090815260408083208884526007019091529020935061491b84614c77565b15614970576002880154600160a060020a038b8116911614925061494684888563ffffffff614e3f16565b909250905061495b868363ffffffff61485916565b955061496d878263ffffffff61485916565b96505b6001909401936148df565b868855600188018690555b5050505060069093019390935550505050565b600160a060020a038216600090815260056020908152604080832084845260088101909252822090916149cc8585610806565b15156149d757600080fd5b50805482546149ec908263ffffffff61485916565b83556002830154600160a060020a0316600090815260056020526040902060030154614a1e908263ffffffff61485916565b6002840154600160a060020a0316600090815260056020526040902060030155600754614a51908263ffffffff61485916565b60075560016002840154614a6d90600160a060020a0316613484565b6001811115614a7857fe5b1415614b73576002830154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe90600890600160a060020a0316614b02858563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515613e0e57600080fd5b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515614b5e57600080fd5b6102c65a03f41515614b6f57600080fd5b5050505b6000848152600884016020526040808220828155600101919091556002840154600160a060020a03808816929116907f9f5b64cc71e1e26ff178caaa7877a04d8ce66fde989251870e80e6fbee690c1790879085905191825260208201526040908101905180910390a35050505050565b600882015460009060ff1615614c4d57614c02828460050154614633565b6001840154909150614c1a908263ffffffff61485916565b6001840155614c43614c32838363ffffffff61465f16565b60078501549063ffffffff61485916565b6007840155614c68565b6001830154614c62908363ffffffff61485916565b60018401555b505050565b620f424090111590565b600301546000901190565b60088301546000908190819060ff1615614cab57614ca1868686614f8c565b9092509050614cbc565b614cb6868686614fd9565b90925090505b614ccc828263ffffffff61485916565b9695505050505050565b60008054600160a060020a031663e16c7d986040517f4c69766570656572546f6b656e000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561442a57600080fd5b60088301546000908190819060ff1615614d7757614ca186868661504b565b614cb6868686615093565b600882015460009060ff1615614de457614da0828460040154614633565b9050614dc3614db5838363ffffffff61465f16565b84549063ffffffff61485916565b83556006830154614dda908263ffffffff61485916565b6006840155614c68565b8254614df6908363ffffffff61485916565b8355505050565b600080831515614e10576000915061486c565b50828202828482811515614e2057fe5b041461486857fe5b6000808284811515614e3657fe5b04949350505050565b6008830154600090819081908190819081908190819060ff1615614eea57614e688b8b8b61504b565b9094509250614e7d848463ffffffff61485916565b9550614e8a8b8b8b614f8c565b9092509050614e9f828263ffffffff61485916565b60018c0154909550614eb7908563ffffffff61465f16565b60018c01558a54614ece908363ffffffff61465f16565b8b558815614ee557600060078c0181905560068c01555b614f5e565b614ef58b8b8b615093565b9094509250614f0a848463ffffffff61485916565b9550614f178b8b8b614fd9565b9092509050614f2c828263ffffffff61485916565b60018c0154909550614f44908763ffffffff61465f16565b60018c01558a54614f5b908663ffffffff61465f16565b8b555b60038b0154614f73908b63ffffffff61465f16565b6003909b019a909a555092989197509095505050505050565b600080600080866003015411614fa3576000614fb6565b614fb68660000154868860030154615113565b905083614fc557806000614fcc565b8086600601545b9250925050935093915050565b6003830154600090819081908190819011156150285761500187600001548860040154614633565b87549092506150259061501a908463ffffffff61465f16565b878960030154615113565b90505b841561503957808293509350615041565b925060009150825b5050935093915050565b600080600080866003015411615062576000615075565b6150758660010154868860030154615113565b90508361508457806000614fcc565b60079095015494959350505050565b6000806000806000809250600091506000886003015411156150ed576150c188600101548960050154614633565b60018901549091506150d9908263ffffffff61465f16565b92506150ea81888a60030154615113565b91505b85156150fe57818394509450615108565b9093506000925083905b505050935093915050565b6000615136620f424061464c615129868661513e565b879063ffffffff614dfd16565b949350505050565b60006146588261464c85620f424063ffffffff614dfd16565b815481835581811511614c6857600083815260209020614c6891810190830161518d565b60206040519081016040526000815290565b6120ef91905b808211156151a75760008155600101615193565b509056009f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd674a165627a7a7230582025ef67cab8ec00693d861b911945d105d5c571279896c9f8476b21968d691dbe0029000000000000000000000000f96d54e490317c557a967abfa5d6e33006be69b3
Deployed Bytecode
0x6060604052600436106101f55763ffffffff60e060020a600035041663038424c381146101fa5780630fd02fc11461021f5780631544fc6714610255578063228cb7331461029857806322bf9d7c146102ad578063235c9603146102d8578063242ed69f1461031357806324454fc41461032657806324b1babf1461039557806325d5971f146103ab57806327de9e32146103c15780632a4e0d55146103d75780633a080e93146103ea5780633aeb512c1461040c5780633da1c2f514610431578063412f83b614610447578063476343ee1461048157806351720b41146104945780635a2a75a9146104a75780635c50c356146104ba5780635dce9948146104cd57806360c79d001461052a57806361e25d2314610540578063673a456b1461055357806368ba170c146105695780636cf6d6751461058857806372d9f13d146105b857806377517765146105ce5780637c0207cb146105e457806385aaff621461060657806388a6c749146106225780638b2f16521461063557806391fdf6b11461066457806392eefe9b146106805780639d0b2c7a1461069f5780639ef9df94146106c1578063a64ad595146106e0578063b78d27dc14610751578063eaffb3f914610773578063f10d1de114610789578063f2083220146107a9578063f595f1cc146107cb578063f77c4791146107ed575b600080fd5b341561020557600080fd5b61020d610800565b60405190815260200160405180910390f35b341561022a57600080fd5b610241600160a060020a0360043516602435610806565b604051901515815260200160405180910390f35b341561026057600080fd5b610274600160a060020a0360043516610837565b6040518082600281111561028457fe5b60ff16815260200191505060405180910390f35b34156102a357600080fd5b6102ab610974565b005b34156102b857600080fd5b6102ab600160a060020a0360043581169060243516604435606435610c13565b34156102e357600080fd5b6102f7600160a060020a03600435166110e6565b604051600160a060020a03909116815260200160405180910390f35b341561031e57600080fd5b6102ab611171565b341561033157600080fd5b610348600160a060020a03600435166024356116da565b60405198895260208901979097526040808901969096526060880194909452608087019290925260a086015260c085015260e0840152901515610100830152610120909101905180910390f35b34156103a057600080fd5b6102ab600435611741565b34156103b657600080fd5b6102ab6004356118cb565b34156103cc57600080fd5b6102ab600435611b57565b34156103e257600080fd5b61020d612078565b34156103f557600080fd5b6102ab600160a060020a03600435166024356120f2565b341561041757600080fd5b6102ab600160a060020a03600435166024356044356122d0565b341561043c57600080fd5b61020d60043561245b565b341561045257600080fd5b610469600160a060020a0360043516602435612470565b60405191825260208201526040908101905180910390f35b341561048c57600080fd5b6102ab6124a4565b341561049f57600080fd5b61020d61267f565b34156104b257600080fd5b61020d612685565b34156104c557600080fd5b61020d6126df565b34156104d857600080fd5b6104ec600160a060020a03600435166126e5565b60405196875260208701959095526040808701949094526060860192909252608085015260a084015260c083019190915260e0909101905180910390f35b341561053557600080fd5b6102ab60043561272e565b341561054b57600080fd5b61020d612880565b341561055e57600080fd5b6102ab600435612886565b341561057457600080fd5b610241600160a060020a03600435166129e4565b341561059357600080fd5b61059b612a03565b60405167ffffffffffffffff909116815260200160405180910390f35b34156105c357600080fd5b6102ab600435612a13565b34156105d957600080fd5b61020d600435612af1565b34156105ef57600080fd5b610241600160a060020a0360043516602435612b06565b341561061157600080fd5b6102ab600435602435604435612b34565b341561062d57600080fd5b6102f761342a565b341561064057600080fd5b610654600160a060020a0360043516613484565b6040518082600181111561028457fe5b341561066f57600080fd5b6102f760043560243560443561351d565b341561068b57600080fd5b6102ab600160a060020a03600435166136ee565b34156106aa57600080fd5b61020d600160a060020a0360043516602435613771565b34156106cc57600080fd5b61020d600160a060020a03600435166138b1565b34156106eb57600080fd5b6106ff600160a060020a036004351661391a565b6040518088815260200187815260200186600160a060020a0316600160a060020a0316815260200185815260200184815260200183815260200182815260200197505050505050505060405180910390f35b341561075c57600080fd5b6102ab600435600160a060020a0360243516613966565b341561077e57600080fd5b6102ab600435613fbb565b341561079457600080fd5b6102ab67ffffffffffffffff600435166140d3565b34156107b457600080fd5b61020d600160a060020a03600435166024356141c9565b34156107d657600080fd5b61020d600160a060020a036004351660243561422d565b34156107f857600080fd5b6102f7614399565b60045481565b600160a060020a03821660009081526005602090815260408083208484526008019091528120600101541192915050565b600160a060020a038116600090815260056020526040812080541515610860576002915061096e565b6108686143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156108ad57600080fd5b6102c65a03f115156108be57600080fd5b50505060405180519050816004015411156108dc576000915061096e565b6000816004015411801561095b57506108f36143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561093857600080fd5b6102c65a03f1151561094957600080fd5b50505060405180519050816004015411155b15610969576001915061096e565b600291505b50919050565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156109be57600080fd5b6102c65a03f115156109cf57600080fd5b50505060405180511590506109e357600080fd5b6109eb6143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610a3057600080fd5b6102c65a03f11515610a4157600080fd5b505050604051805190501515610a5657600080fd5b610a5e6143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610aa357600080fd5b6102c65a03f11515610ab457600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a033316845260010190915290205490935060ff1615159050610af557600080fd5b600160a060020a033316600090815260066020526040902054821415610b1a57600080fd5b600160a060020a0333166000908152600660205260409020829055610b3d61443b565b600160a060020a0316637dbedad5610b5533856141c9565b6000858152600d6020526040808220600201549190516020015260405160e060020a63ffffffff851602815260048101929092526024820152604401602060405180830381600087803b1515610baa57600080fd5b6102c65a03f11515610bbb57600080fd5b505050604051805190509050610bd23382846144bd565b33600160a060020a03167f619caafabdd75649b302ba8419e48cccf64f37f1983ac4727cfb38b57703ffc98260405190815260200160405180910390a25050565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610c6157600080fd5b6102c65a03f11515610c7257600080fd5b5050506040518051159050610c8657600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610d0757600080fd5b6102c65a03f11515610d1857600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515610d4157600080fd5b600160a060020a03881660009081526005602052604081208054909550111561107757600160a060020a038816600090815260056020526040902054610d879087614633565b8454909350610d9c908463ffffffff61465f16565b84556001610da989610837565b6002811115610db457fe5b1415610e21576002840154600160a060020a0316600090815260056020526040902060030154610dea908463ffffffff61465f16565b6002850154600160a060020a0316600090815260056020526040902060030155600754610e1d908463ffffffff61465f16565b6007555b6001610e2c89613484565b6001811115610e3757fe5b1415610e4657610e4688614671565b829150600160a060020a03871615610fab57610e628386614633565b9050610e6c61443b565b600160a060020a031663e7a49c2b888360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515610ebf57600080fd5b6102c65a03f11515610ed057600080fd5b505050610edb61443b565b600160a060020a031663c7ee98c2610ef9848463ffffffff61465f16565b60405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610f2f57600080fd5b6102c65a03f11515610f4057600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c228885846040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a2611072565b610fb361443b565b600160a060020a031663c7ee98c28360405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610ff857600080fd5b6102c65a03f1151561100957600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c2260008560006040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b6110dc565b87600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c22886000806040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b5050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561114f57600080fd5b6102c65a03f4151561116057600080fd5b50505060405180519150505b919050565b6000806000806000806000806000806000809054906101000a9004600160a060020a0316600160a060020a0316635c975abb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156111da57600080fd5b6102c65a03f115156111eb57600080fd5b50505060405180511590506111ff57600080fd5b600054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561128057600080fd5b6102c65a03f1151561129157600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156112ba57600080fd5b6112c26143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561130757600080fd5b6102c65a03f1151561131857600080fd5b5050506040518051600354909b506113a49150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561138457600080fd5b6102c65a03f4151561139557600080fd5b5050506040518051905061481a565b985060009750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed60088a6040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561140257600080fd5b6102c65a03f4151561141357600080fd5b5050506040518051975060009650505b888610156116ba5760008a8152600d602052604090208054600181016114498382615157565b506000918252602080832091909101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038b169081179091558c8352600d825260408084209184526001918201909252818320805460ff19169091179055731a0b2ca69ca2c7f96e2529faa6d63f881655d81a9163d8681128916008918b91516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561150e57600080fd5b6102c65a03f4151561151f57600080fd5b5050506040518051905094506006600088600160a060020a0316600160a060020a031681526020019081526020016000206004015493506006600088600160a060020a0316600160a060020a031681526020019081526020016000206005015492506006600088600160a060020a0316600160a060020a031681526020019081526020016000206006015491506006600088600160a060020a0316600160a060020a0316815260200190815260200160002090508381600101819055508281600201819055508181600301819055506116198585858460070160008f8152602001908152602001600020614830909392919063ffffffff16565b611629888663ffffffff61485916565b9750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088960006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561169357600080fd5b6102c65a03f415156116a457600080fd5b5050506040518051975050600190950194611423565b50505060009687525050600d602052505060409092206002019190915550565b600160a060020a03909116600090815260066020818152604080842094845260079485019091529091208054600182015460028301546003840154600485015460058601549686015497860154600890960154949893979296919590949193909160ff1690565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561178a57600080fd5b6102c65a03f1151561179b57600080fd5b50505060405180511590506117af57600080fd5b6117b76143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156117fc57600080fd5b6102c65a03f1151561180d57600080fd5b50505060405180519050151561182257600080fd5b600160a060020a03331660009081526005602052604090206006015481901061184a57600080fd5b6118526143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561189757600080fd5b6102c65a03f115156118a857600080fd5b505050604051805182111590506118be57600080fd5b6118c83382614873565b50565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561191957600080fd5b6102c65a03f1151561192a57600080fd5b505050604051805115905061193e57600080fd5b6119466143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561198b57600080fd5b6102c65a03f1151561199c57600080fd5b5050506040518051905015156119b157600080fd5b33600160a060020a03811660009081526005602090815260408083208984526008810190925290912090955093506119e99086610806565b15156119f457600080fd5b6119fc6143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611a4157600080fd5b6102c65a03f11515611a5257600080fd5b5050506040518051600185015411159050611a6c57600080fd5b505080546001808301546000868152600886016020526040812081815590920191909155611a9861443b565b600160a060020a031663e7a49c2b338460405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515611aeb57600080fd5b6102c65a03f11515611afc57600080fd5b50505033600160a060020a03167f1340f1a8f3d456a649e1a12071dfa15655e3d09252131d0f980c3b405cc8dd2e86848460405180848152602001838152602001828152602001935050505060405180910390a25050505050565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611ba557600080fd5b6102c65a03f11515611bb657600080fd5b5050506040518051159050611bca57600080fd5b611bd26143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611c1757600080fd5b6102c65a03f11515611c2857600080fd5b505050604051805190501515611c3d57600080fd5b611cae33611c496143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611c8e57600080fd5b6102c65a03f11515611c9f57600080fd5b50505060405180519050614873565b6001611cb933610837565b6002811115611cc457fe5b14611cce57600080fd5b600160a060020a033316600090815260056020526040812094508511611cf357600080fd5b8354851115611d0157600080fd5b611d096143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611d4e57600080fd5b6102c65a03f11515611d5f57600080fd5b5050506040518051600254909450611d899150849067ffffffffffffffff1663ffffffff61485916565b915083600701549050604080519081016040908152868252602080830185905260008481526008880190915220815181556020820151600191820155611dd79150829063ffffffff61485916565b60078501558354611dee908663ffffffff61465f16565b84556002840154600160a060020a0316600090815260056020526040902060030154611e20908663ffffffff61465f16565b6002850154600160a060020a0316600090815260056020526040902060030155600754611e53908663ffffffff61465f16565b60075560016002850154611e6f90600160a060020a0316613484565b6001811115611e7a57fe5b148015611ea45750600284015433600160a060020a039081169116141580611ea457508354600090115b15611fc5576002840154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe90600890600160a060020a0316611f54898563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515611f2d57600080fd5b6102c65a03f41515611f3e57600080fd5b505050604051805191905063ffffffff61465f16565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515611fb057600080fd5b6102c65a03f41515611fc157600080fd5b5050505b835415156120185760028401805473ffffffffffffffffffffffffffffffffffffffff19169055600060048501556001611ffe33613484565b600181111561200957fe5b14156120185761201833614671565b6002840154600160a060020a0333811691167f2d5d98d189bee5496a08db2a5948cb7e5e786f09d17d0c3f228eb41776c24a0683888660405180848152602001838152602001828152602001935050505060405180910390a35050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece586008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156120d257600080fd5b6102c65a03f415156120e357600080fd5b50505060405180519150505b90565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561213b57600080fd5b6102c65a03f1151561214c57600080fd5b505050604051805115905061216057600080fd5b6121686143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156121ad57600080fd5b6102c65a03f115156121be57600080fd5b5050506040518051905015156121d357600080fd5b6121df33611c496143a8565b60026121ea33610837565b60028111156121f557fe5b146121ff57600080fd5b612278600161220c6143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561225157600080fd5b6102c65a03f1151561226257600080fd5b505050604051805191905063ffffffff61485916565b33600160a060020a03818116600090815260056020526040902060048101939093556002909201805473ffffffffffffffffffffffffffffffffffffffff1916928516929092179091556122cc9082614999565b5050565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561231a57600080fd5b6102c65a03f1151561232b57600080fd5b505050604051805115905061233f57600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156123c057600080fd5b6102c65a03f115156123d157600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156123fa57600080fd5b600161240586613484565b600181111561241057fe5b1461241a57600080fd5b5050600160a060020a038316600090815260066020908152604080832084845260078101909252909120612454818563ffffffff614be416565b5050505050565b600d6020526000908152604090206002015481565b600160a060020a03919091166000908152600560209081526040808320938352600890930190522080546001909101549091565b60008054600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156124ec57600080fd5b6102c65a03f115156124fd57600080fd5b505050604051805115905061251157600080fd5b6125196143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561255e57600080fd5b6102c65a03f1151561256f57600080fd5b50505060405180519050151561258457600080fd5b61259033611c496143a8565b600160a060020a033316600090815260056020526040812060010154116125b657600080fd5b50600160a060020a033316600090815260056020526040812060010180549190556125df61443b565b600160a060020a03166320283da9338360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b151561263257600080fd5b6102c65a03f1151561264357600080fd5b50505033600160a060020a03167fd3719f04262b628e1d01a6ed24707f542cda51f144b5271149c7d0419436d00c60405160405180910390a250565b60015481565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156120d257600080fd5b60075490565b600160a060020a03166000908152600660208190526040909120805460018201546002830154600384015460048501546005860154959096015493969295919490939192909190565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561277757600080fd5b6102c65a03f1151561278857600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156127b157600080fd5b6003548110156127c057600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63a176adaf60088360405160e060020a63ffffffff85160281526004810192909252602482015260440160006040518083038186803b151561281657600080fd5b6102c65a03f4151561282757600080fd5b5050506000805160206151ac8339815191526040516020808252600e908201527f6e756d5472616e73636f646572730000000000000000000000000000000000006040808301919091526060909101905180910390a150565b60035481565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156128cf57600080fd5b6102c65a03f115156128e057600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561290957600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561296257600080fd5b6102c65a03f4151561297357600080fd5b5050506040518051821115905061298957600080fd5b60038190556000805160206151ac83398151915260405160208082526014908201527f6e756d4163746976655472616e73636f646572730000000000000000000000006040808301919091526060909101905180910390a150565b600060016129f183613484565b60018111156129fc57fe5b1492915050565b60025467ffffffffffffffff1681565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612a5c57600080fd5b6102c65a03f11515612a6d57600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515612a9657600080fd5b60048190556000805160206151ac83398151915260405160208082526017908201527f6d61784561726e696e6773436c61696d73526f756e64730000000000000000006040808301919091526060909101905180910390a150565b6000908152600d602052604090206002015490565b6000908152600d60209081526040808320600160a060020a0394909416835260019093019052205460ff1690565b60008054819081908190819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612b8857600080fd5b6102c65a03f11515612b9957600080fd5b5050506040518051159050612bad57600080fd5b612bb56143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612bfa57600080fd5b6102c65a03f11515612c0b57600080fd5b505050604051805190501515612c2057600080fd5b600160a060020a033316600090815260066020908152604080832060059092529091209097509550612c506143a8565b600160a060020a0316636841f2536000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612c9557600080fd5b6102c65a03f11515612ca657600080fd5b5050506040518051905015612f6c576001612cc033613484565b6001811115612ccb57fe5b14612cd557600080fd5b60048701548a14612ce557600080fd5b60058701548914612cf557600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612d4e57600080fd5b6102c65a03f41515612d5f57600080fd5b5050506040518051600160a060020a0381166000908152600660208190526040822001549197509095509350505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612de657600080fd5b6102c65a03f41515612df757600080fd5b50505060405180519050831015612edc57600160a060020a0385166000908152600660208190526040909120015484901015612e4d57600160a060020a0385166000908152600660208190526040909120015493505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088760006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612eb557600080fd5b6102c65a03f41515612ec657600080fd5b5050506040518051955050600190920191612d8d565b838810158015612ef0575086600601548811155b1515612efb57600080fd5b87876006018190555033600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be7886004015489600501548b6001604051938452602084019290925260408084019190915290151560608301526080909101905180910390a261341e565b612f758a614c6d565b1515612f8057600080fd5b612f8989614c6d565b1515612f9457600080fd5b600286015433600160a060020a039081169116148015612fb657508554600090115b1515612fc157600080fd5b600487018a90556005870189905560068701889055600386015491506000612fe833613484565b6001811115612ff357fe5b141561333f57731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634aa12990600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561305257600080fd5b6102c65a03f4151561306357600080fd5b50505060405180519050151561310657731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a66008338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156130ed57600080fd5b6102c65a03f415156130fe57600080fd5b50505061333f565b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6372e40b26600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561315f57600080fd5b6102c65a03f4151561317057600080fd5b50505060405180519150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a905063d868112860088360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156131e457600080fd5b6102c65a03f415156131f557600080fd5b5050506040518051905082111561333f57731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088360405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b151561326557600080fd5b6102c65a03f4151561327657600080fd5b5050506008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a69091338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156132f557600080fd5b6102c65a03f4151561330657600080fd5b50505080600160a060020a03167e05588101bf85a737dacb8be2233b33113aaa5c5743525cfbfe2f6a77c2f6ff60405160405180910390a25b33600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be78b8b8b6008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c4790913360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156133d757600080fd5b6102c65a03f415156133e857600080fd5b50505060405180519050604051938452602084019290925260408084019190915290151560608301526080909101905180910390a25b50505050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156120d257600080fd5b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c47600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156134ed57600080fd5b6102c65a03f415156134fe57600080fd5b50505060405180519050156135155750600161116c565b50600061116c565b60008061352861517b565b6000848152600d60205260408082205493508190819081908190819081908990518059106135535750595b908082528060200260200182016040525097506000965060009550600094505b8885101561364e5760008b8152600d6020526040902080548690811061359557fe5b60009182526020808320909101548d8352600d82526040808420600160a060020a0390921680855260019290920190925291205490945060ff1680156135f75750600160a060020a0384166000908152600660205260409020600301548d9011155b15613643578388888151811061360957fe5b600160a060020a03909216602092830290910190910152600190960195613640613633858d6141c9565b879063ffffffff61485916565b95505b600190940193613573565b86151561365e57600099506136de565b858c81151561366957fe5b06925060009150600090505b82821115801561368457508681105b156136c2576136b86136ab89838151811061369b57fe5b906020019060200201518d6141c9565b839063ffffffff61485916565b9150600101613675565b8760018203815181106136d157fe5b9060200190602002015199505b5050505050505050509392505050565b60005433600160a060020a0390811691161461370957600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f7081604051600160a060020a03909116815260200160405180910390a150565b60008060008060008060006137846143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156137c957600080fd5b6102c65a03f115156137da57600080fd5b5050506040518051600160a060020a038b1660009081526005602052604090209097509550508588118015906138135750846006015488115b151561381e57600080fd5b8454600686015490945060010192505b8783116138a45750506002830154600160a060020a03908116600081815260066020908152604080832086845260070190915290209189161461387082614c77565b156138995761389661388983868463ffffffff614c8216565b859063ffffffff61485916565b93505b60019092019161382e565b5091979650505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d8681128600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561114f57600080fd5b600160a060020a03908116600090815260056020526040902080546001820154600283015460038401546004850154600686015460079096015494979396929092169490939192909190565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156139b457600080fd5b6102c65a03f115156139c557600080fd5b50505060405180511590506139d957600080fd5b6139e16143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613a2657600080fd5b6102c65a03f11515613a3757600080fd5b505050604051805190501515613a4c57600080fd5b613a5833611c496143a8565b600160a060020a03331660009081526005602052604090209350613a7a6143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613abf57600080fd5b6102c65a03f11515613ad057600080fd5b5050506040518051600280870154919550889450600160a060020a0390911692509050613afc33610837565b6002811115613b0757fe5b1415613b2857613b1e83600163ffffffff61485916565b6004850155613cf6565b6002840154600160a060020a031615801590613b5457506002840154600160a060020a03868116911614155b15613cf6576000613b6433613484565b6001811115613b6f57fe5b14613b7957600080fd5b613b8a83600163ffffffff61485916565b60048501558354613ba290839063ffffffff61485916565b8454600160a060020a038316600090815260056020526040902060030154919350613bd3919063ffffffff61465f16565b600160a060020a0382166000908152600560205260409020600301556001613bfa82613484565b6001811115613c0557fe5b1415613cf6578354731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe906008908490613c85908563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515611f2d57600080fd5b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515613ce157600080fd5b6102c65a03f41515613cf257600080fd5b5050505b60008211613d0357600080fd5b60028401805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038716908117909155600090815260056020526040902060030154613d4c9083614859565b600160a060020a0386166000908152600560205260409020600301556001613d7386613484565b6001811115613d7e57fe5b1415613e90576002840154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe906008908890613e1f908790869063d8681128908690600160a060020a031660006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515613e0e57600080fd5b6102c65a03f4151561226257600080fd5b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515613e7b57600080fd5b6102c65a03f41515613e8c57600080fd5b5050505b6000861115613f57578354613eab908763ffffffff61485916565b8455600754613ec0908763ffffffff61485916565b600755613ecb614cd6565b600160a060020a03166323b872dd33613ee261443b565b8960006040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b1515613f3b57600080fd5b6102c65a03f11515613f4c57600080fd5b505050604051805150505b33600160a060020a031681600160a060020a031686600160a060020a03167fe5917769f276ddca9f2ee7c6b0b33e1d1e1b61008010ce622c632dd20d168a2389886000015460405191825260208201526040908101905180910390a4505050505050565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561400457600080fd5b6102c65a03f1151561401557600080fd5b505050604051805115905061402957600080fd5b6140316143a8565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561407657600080fd5b6102c65a03f1151561408757600080fd5b50505060405180519050151561409c57600080fd5b6140a833611c496143a8565b60026140b333610837565b60028111156140be57fe5b14156140c957600080fd5b6118c83382614999565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561411c57600080fd5b6102c65a03f1151561412d57600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561415657600080fd5b6002805467ffffffffffffffff191667ffffffffffffffff83161790556000805160206151ac8339815191526040516020808252600f908201527f756e626f6e64696e67506572696f6400000000000000000000000000000000006040808301919091526060909101905180910390a150565b6000818152600d60209081526040808320600160a060020a038616845260010190915281205460ff1615156141fd57600080fd5b50600160a060020a0391909116600090815260066020908152604080832093835260079093019052206002015490565b6000806000806000806000806142416143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561428657600080fd5b6102c65a03f1151561429757600080fd5b5050506040518051600160a060020a038c1660009081526005602052604090209098509650508689118015906142d05750856006015489115b15156142db57600080fd5b6001808701548754600689015491975095500192505b88831161438b576002860154600160a060020a031660009081526006602090815260408083208684526007019091529020915061432d82614c77565b1561438057506002850154600160a060020a038a811691161461436761435a83868463ffffffff614d5816565b869063ffffffff61485916565b945061437d61388983868463ffffffff614c8216565b93505b6001909201916142f1565b509298975050505050505050565b600054600160a060020a031681565b60008054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561442a57600080fd5b6102c65a03f115156120e357600080fd5b60008054600160a060020a031663e16c7d986040517f4d696e74657200000000000000000000000000000000000000000000000000008152600601604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561442a57600080fd5b600160a060020a0383166000908152600660209081526040808320600583528184208585526007820190935290832090926144fe828763ffffffff614d8216565b6003830154614513908763ffffffff61485916565b600384015561458486731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d868112860088b60006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515613e0e57600080fd5b9050731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6338237efe6008898460008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561460057600080fd5b6102c65a03f4151561461157600080fd5b505060075461462791508763ffffffff61485916565b60075550505050505050565b6000614658620f424061464c858563ffffffff614dfd16565b9063ffffffff614e2816565b9392505050565b60008282111561466b57fe5b50900390565b600061467b6143a8565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156146c057600080fd5b6102c65a03f115156146d157600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a038816845260010190915290205490925060ff1615905061476d5761473761471983836141c9565b6000838152600d60205260409020600201549063ffffffff61465f16565b6000828152600d602090815260408083206002810194909455600160a060020a03861683526001909301905220805460ff191690555b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088460405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b15156147cc57600080fd5b6102c65a03f415156147dd57600080fd5b50505081600160a060020a03167fc6be59bdc33151833b6dbb6823a9bddecde3c685a1bf4d253d20b4a93fbae56c60405160405180910390a25050565b60008183106148295781614658565b5090919050565b60028401839055600384019290925560048301556005820155600801805460ff19166001179055565b60008282018381101561486857fe5b8091505b5092915050565b600160a060020a0380831660009081526005602052604081206002810154909282918291829182918291829116156149865760045460068901546148be908b9063ffffffff61465f16565b11156148c957600080fd5b87546001808a015460068b015492995097500194505b88851161497b576002880154600160a060020a031660009081526006602090815260408083208884526007019091529020935061491b84614c77565b15614970576002880154600160a060020a038b8116911614925061494684888563ffffffff614e3f16565b909250905061495b868363ffffffff61485916565b955061496d878263ffffffff61485916565b96505b6001909401936148df565b868855600188018690555b5050505060069093019390935550505050565b600160a060020a038216600090815260056020908152604080832084845260088101909252822090916149cc8585610806565b15156149d757600080fd5b50805482546149ec908263ffffffff61485916565b83556002830154600160a060020a0316600090815260056020526040902060030154614a1e908263ffffffff61485916565b6002840154600160a060020a0316600090815260056020526040902060030155600754614a51908263ffffffff61485916565b60075560016002840154614a6d90600160a060020a0316613484565b6001811115614a7857fe5b1415614b73576002830154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe90600890600160a060020a0316614b02858563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515613e0e57600080fd5b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515614b5e57600080fd5b6102c65a03f41515614b6f57600080fd5b5050505b6000848152600884016020526040808220828155600101919091556002840154600160a060020a03808816929116907f9f5b64cc71e1e26ff178caaa7877a04d8ce66fde989251870e80e6fbee690c1790879085905191825260208201526040908101905180910390a35050505050565b600882015460009060ff1615614c4d57614c02828460050154614633565b6001840154909150614c1a908263ffffffff61485916565b6001840155614c43614c32838363ffffffff61465f16565b60078501549063ffffffff61485916565b6007840155614c68565b6001830154614c62908363ffffffff61485916565b60018401555b505050565b620f424090111590565b600301546000901190565b60088301546000908190819060ff1615614cab57614ca1868686614f8c565b9092509050614cbc565b614cb6868686614fd9565b90925090505b614ccc828263ffffffff61485916565b9695505050505050565b60008054600160a060020a031663e16c7d986040517f4c69766570656572546f6b656e000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561442a57600080fd5b60088301546000908190819060ff1615614d7757614ca186868661504b565b614cb6868686615093565b600882015460009060ff1615614de457614da0828460040154614633565b9050614dc3614db5838363ffffffff61465f16565b84549063ffffffff61485916565b83556006830154614dda908263ffffffff61485916565b6006840155614c68565b8254614df6908363ffffffff61485916565b8355505050565b600080831515614e10576000915061486c565b50828202828482811515614e2057fe5b041461486857fe5b6000808284811515614e3657fe5b04949350505050565b6008830154600090819081908190819081908190819060ff1615614eea57614e688b8b8b61504b565b9094509250614e7d848463ffffffff61485916565b9550614e8a8b8b8b614f8c565b9092509050614e9f828263ffffffff61485916565b60018c0154909550614eb7908563ffffffff61465f16565b60018c01558a54614ece908363ffffffff61465f16565b8b558815614ee557600060078c0181905560068c01555b614f5e565b614ef58b8b8b615093565b9094509250614f0a848463ffffffff61485916565b9550614f178b8b8b614fd9565b9092509050614f2c828263ffffffff61485916565b60018c0154909550614f44908763ffffffff61465f16565b60018c01558a54614f5b908663ffffffff61465f16565b8b555b60038b0154614f73908b63ffffffff61465f16565b6003909b019a909a555092989197509095505050505050565b600080600080866003015411614fa3576000614fb6565b614fb68660000154868860030154615113565b905083614fc557806000614fcc565b8086600601545b9250925050935093915050565b6003830154600090819081908190819011156150285761500187600001548860040154614633565b87549092506150259061501a908463ffffffff61465f16565b878960030154615113565b90505b841561503957808293509350615041565b925060009150825b5050935093915050565b600080600080866003015411615062576000615075565b6150758660010154868860030154615113565b90508361508457806000614fcc565b60079095015494959350505050565b6000806000806000809250600091506000886003015411156150ed576150c188600101548960050154614633565b60018901549091506150d9908263ffffffff61465f16565b92506150ea81888a60030154615113565b91505b85156150fe57818394509450615108565b9093506000925083905b505050935093915050565b6000615136620f424061464c615129868661513e565b879063ffffffff614dfd16565b949350505050565b60006146588261464c85620f424063ffffffff614dfd16565b815481835581811511614c6857600083815260209020614c6891810190830161518d565b60206040519081016040526000815290565b6120ef91905b808211156151a75760008155600101615193565b509056009f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd674a165627a7a7230582025ef67cab8ec00693d861b911945d105d5c571279896c9f8476b21968d691dbe0029
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f96d54e490317c557a967abfa5d6e33006be69b3
-----Decoded View---------------
Arg [0] : _controller (address): 0xF96D54E490317c557A967ABfA5d6e33006BE69b3
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000f96d54e490317c557a967abfa5d6e33006be69b3
Swarm Source
bzzr://25ef67cab8ec00693d861b911945d105d5c571279896c9f8476b21968d691dbe
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.