Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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-05-27 */ pragma solidity 0.4.18; /** * @title ERC20Basic * @dev Simpler version of ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/179 */ contract ERC20Basic { uint256 public totalSupply; function balanceOf(address who) public view returns (uint256); function transfer(address to, uint256 value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); } /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ contract ERC20 is ERC20Basic { function allowance(address owner, address spender) public view returns (uint256); function transferFrom(address from, address to, uint256 value) public returns (bool); function approve(address spender, uint256 value) public returns (bool); event Approval(address indexed owner, address indexed spender, uint256 value); } /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ contract Ownable { address public owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ function Ownable() public { owner = msg.sender; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(msg.sender == owner); _; } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) public onlyOwner { require(newOwner != address(0)); OwnershipTransferred(owner, newOwner); owner = newOwner; } } /** * @title Pausable * @dev Base contract which allows children to implement an emergency stop mechanism. */ contract Pausable is Ownable { event Pause(); event Unpause(); bool public paused = false; /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!paused); _; } /** * @dev Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { require(paused); _; } /** * @dev called by the owner to pause, triggers stopped state */ function pause() onlyOwner whenNotPaused public { paused = true; Pause(); } /** * @dev called by the owner to unpause, returns to normal state */ function unpause() onlyOwner whenPaused public { paused = false; Unpause(); } } /** * @title Math * @dev Assorted math operations */ library Math { function max64(uint64 a, uint64 b) internal pure returns (uint64) { return a >= b ? a : b; } function min64(uint64 a, uint64 b) internal pure returns (uint64) { return a < b ? a : b; } function max256(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } function min256(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } } /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; assert(c / a == b); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { // assert(b > 0); // Solidity automatically throws when dividing by 0 uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; } } library MathUtils { using SafeMath for uint256; // Divisor used for representing percentages uint256 public constant PERC_DIVISOR = 1000000; /* * @dev Returns whether an amount is a valid percentage out of PERC_DIVISOR * @param _amount Amount that is supposed to be a percentage */ function validPerc(uint256 _amount) internal pure returns (bool) { return _amount <= PERC_DIVISOR; } /* * @dev Compute percentage of a value with the percentage represented by a fraction * @param _amount Amount to take the percentage of * @param _fracNum Numerator of fraction representing the percentage * @param _fracDenom Denominator of fraction representing the percentage */ function percOf(uint256 _amount, uint256 _fracNum, uint256 _fracDenom) internal pure returns (uint256) { return _amount.mul(percPoints(_fracNum, _fracDenom)).div(PERC_DIVISOR); } /* * @dev Compute percentage of a value with the percentage represented by a fraction over PERC_DIVISOR * @param _amount Amount to take the percentage of * @param _fracNum Numerator of fraction representing the percentage with PERC_DIVISOR as the denominator */ function percOf(uint256 _amount, uint256 _fracNum) internal pure returns (uint256) { return _amount.mul(_fracNum).div(PERC_DIVISOR); } /* * @dev Compute percentage representation of a fraction * @param _fracNum Numerator of fraction represeting the percentage * @param _fracDenom Denominator of fraction represeting the percentage */ function percPoints(uint256 _fracNum, uint256 _fracDenom) internal pure returns (uint256) { return _fracNum.mul(PERC_DIVISOR).div(_fracDenom); } } contract IController is Pausable { event SetContractInfo(bytes32 id, address contractAddress, bytes20 gitCommitHash); function setContractInfo(bytes32 _id, address _contractAddress, bytes20 _gitCommitHash) external; function updateController(bytes32 _id, address _controller) external; function getContract(bytes32 _id) public view returns (address); } contract IManager { event SetController(address controller); event ParameterUpdate(string param); function setController(address _controller) external; } contract Manager is IManager { // Controller that contract is registered with IController public controller; // Check if sender is controller modifier onlyController() { require(msg.sender == address(controller)); _; } // Check if sender is controller owner modifier onlyControllerOwner() { require(msg.sender == controller.owner()); _; } // Check if controller is not paused modifier whenSystemNotPaused() { require(!controller.paused()); _; } // Check if controller is paused modifier whenSystemPaused() { require(controller.paused()); _; } function Manager(address _controller) public { controller = IController(_controller); } /* * @dev Set controller. Only callable by current controller * @param _controller Controller contract address */ function setController(address _controller) external onlyController { controller = IController(_controller); SetController(_controller); } } /** * @title ManagerProxyTarget * @dev The base contract that target contracts used by a proxy contract should inherit from * Note: Both the target contract and the proxy contract (implemented as ManagerProxy) MUST inherit from ManagerProxyTarget in order to guarantee * that both contracts have the same storage layout. Differing storage layouts in a proxy contract and target contract can * potentially break the delegate proxy upgradeability mechanism */ contract ManagerProxyTarget is Manager { // Used to look up target contract address in controller's registry bytes32 public targetContractId; } /* * @title A sorted doubly linked list with nodes sorted in descending order. Optionally accepts insert position hints * * Given a new node with a `key`, a hint is of the form `(prevId, nextId)` s.t. `prevId` and `nextId` are adjacent in the list. * `prevId` is a node with a key >= `key` and `nextId` is a node with a key <= `key`. If the sender provides a hint that is a valid insert position * the insert operation is a constant time storage write. However, the provided hint in a given transaction might be a valid insert position, but if other transactions are included first, when * the given transaction is executed the provided hint may no longer be a valid insert position. For example, one of the nodes referenced might be removed or their keys may * be updated such that the the pair of nodes in the hint no longer represent a valid insert position. If one of the nodes in the hint becomes invalid, we still try to use the other * valid node as a starting point for finding the appropriate insert position. If both nodes in the hint become invalid, we use the head of the list as a starting point * to find the appropriate insert position. */ library SortedDoublyLL { using SafeMath for uint256; // Information for a node in the list struct Node { uint256 key; // Node's key used for sorting address nextId; // Id of next node (smaller key) in the list address prevId; // Id of previous node (larger key) in the list } // Information for the list struct Data { address head; // Head of the list. Also the node in the list with the largest key address tail; // Tail of the list. Also the node in the list with the smallest key uint256 maxSize; // Maximum size of the list uint256 size; // Current size of the list mapping (address => Node) nodes; // Track the corresponding ids for each node in the list } /* * @dev Set the maximum size of the list * @param _size Maximum size */ function setMaxSize(Data storage self, uint256 _size) public { // New max size must be greater than old max size require(_size > self.maxSize); self.maxSize = _size; } /* * @dev Add a node to the list * @param _id Node's id * @param _key Node's key * @param _prevId Id of previous node for the insert position * @param _nextId Id of next node for the insert position */ function insert(Data storage self, address _id, uint256 _key, address _prevId, address _nextId) public { // List must not be full require(!isFull(self)); // List must not already contain node require(!contains(self, _id)); // Node id must not be null require(_id != address(0)); // Key must be non-zero require(_key > 0); address prevId = _prevId; address nextId = _nextId; if (!validInsertPosition(self, _key, prevId, nextId)) { // Sender's hint was not a valid insert position // Use sender's hint to find a valid insert position (prevId, nextId) = findInsertPosition(self, _key, prevId, nextId); } self.nodes[_id].key = _key; if (prevId == address(0) && nextId == address(0)) { // Insert as head and tail self.head = _id; self.tail = _id; } else if (prevId == address(0)) { // Insert before `prevId` as the head self.nodes[_id].nextId = self.head; self.nodes[self.head].prevId = _id; self.head = _id; } else if (nextId == address(0)) { // Insert after `nextId` as the tail self.nodes[_id].prevId = self.tail; self.nodes[self.tail].nextId = _id; self.tail = _id; } else { // Insert at insert position between `prevId` and `nextId` self.nodes[_id].nextId = nextId; self.nodes[_id].prevId = prevId; self.nodes[prevId].nextId = _id; self.nodes[nextId].prevId = _id; } self.size = self.size.add(1); } /* * @dev Remove a node from the list * @param _id Node's id */ function remove(Data storage self, address _id) public { // List must contain the node require(contains(self, _id)); if (self.size > 1) { // List contains more than a single node if (_id == self.head) { // The removed node is the head // Set head to next node self.head = self.nodes[_id].nextId; // Set prev pointer of new head to null self.nodes[self.head].prevId = address(0); } else if (_id == self.tail) { // The removed node is the tail // Set tail to previous node self.tail = self.nodes[_id].prevId; // Set next pointer of new tail to null self.nodes[self.tail].nextId = address(0); } else { // The removed node is neither the head nor the tail // Set next pointer of previous node to the next node self.nodes[self.nodes[_id].prevId].nextId = self.nodes[_id].nextId; // Set prev pointer of next node to the previous node self.nodes[self.nodes[_id].nextId].prevId = self.nodes[_id].prevId; } } else { // List contains a single node // Set the head and tail to null self.head = address(0); self.tail = address(0); } delete self.nodes[_id]; self.size = self.size.sub(1); } /* * @dev Update the key of a node in the list * @param _id Node's id * @param _newKey Node's new key * @param _prevId Id of previous node for the new insert position * @param _nextId Id of next node for the new insert position */ function updateKey(Data storage self, address _id, uint256 _newKey, address _prevId, address _nextId) public { // List must contain the node require(contains(self, _id)); // Remove node from the list remove(self, _id); if (_newKey > 0) { // Insert node if it has a non-zero key insert(self, _id, _newKey, _prevId, _nextId); } } /* * @dev Checks if the list contains a node * @param _transcoder Address of transcoder */ function contains(Data storage self, address _id) public view returns (bool) { // List only contains non-zero keys, so if key is non-zero the node exists return self.nodes[_id].key > 0; } /* * @dev Checks if the list is full */ function isFull(Data storage self) public view returns (bool) { return self.size == self.maxSize; } /* * @dev Checks if the list is empty */ function isEmpty(Data storage self) public view returns (bool) { return self.size == 0; } /* * @dev Returns the current size of the list */ function getSize(Data storage self) public view returns (uint256) { return self.size; } /* * @dev Returns the maximum size of the list */ function getMaxSize(Data storage self) public view returns (uint256) { return self.maxSize; } /* * @dev Returns the key of a node in the list * @param _id Node's id */ function getKey(Data storage self, address _id) public view returns (uint256) { return self.nodes[_id].key; } /* * @dev Returns the first node in the list (node with the largest key) */ function getFirst(Data storage self) public view returns (address) { return self.head; } /* * @dev Returns the last node in the list (node with the smallest key) */ function getLast(Data storage self) public view returns (address) { return self.tail; } /* * @dev Returns the next node (with a smaller key) in the list for a given node * @param _id Node's id */ function getNext(Data storage self, address _id) public view returns (address) { return self.nodes[_id].nextId; } /* * @dev Returns the previous node (with a larger key) in the list for a given node * @param _id Node's id */ function getPrev(Data storage self, address _id) public view returns (address) { return self.nodes[_id].prevId; } /* * @dev Check if a pair of nodes is a valid insertion point for a new node with the given key * @param _key Node's key * @param _prevId Id of previous node for the insert position * @param _nextId Id of next node for the insert position */ function validInsertPosition(Data storage self, uint256 _key, address _prevId, address _nextId) public view returns (bool) { if (_prevId == address(0) && _nextId == address(0)) { // `(null, null)` is a valid insert position if the list is empty return isEmpty(self); } else if (_prevId == address(0)) { // `(null, _nextId)` is a valid insert position if `_nextId` is the head of the list return self.head == _nextId && _key >= self.nodes[_nextId].key; } else if (_nextId == address(0)) { // `(_prevId, null)` is a valid insert position if `_prevId` is the tail of the list return self.tail == _prevId && _key <= self.nodes[_prevId].key; } else { // `(_prevId, _nextId)` is a valid insert position if they are adjacent nodes and `_key` falls between the two nodes' keys return self.nodes[_prevId].nextId == _nextId && self.nodes[_prevId].key >= _key && _key >= self.nodes[_nextId].key; } } /* * @dev Descend the list (larger keys to smaller keys) to find a valid insert position * @param _key Node's key * @param _startId Id of node to start ascending the list from */ function descendList(Data storage self, uint256 _key, address _startId) private view returns (address, address) { // If `_startId` is the head, check if the insert position is before the head if (self.head == _startId && _key >= self.nodes[_startId].key) { return (address(0), _startId); } address prevId = _startId; address nextId = self.nodes[prevId].nextId; // Descend the list until we reach the end or until we find a valid insert position while (prevId != address(0) && !validInsertPosition(self, _key, prevId, nextId)) { prevId = self.nodes[prevId].nextId; nextId = self.nodes[prevId].nextId; } return (prevId, nextId); } /* * @dev Ascend the list (smaller keys to larger keys) to find a valid insert position * @param _key Node's key * @param _startId Id of node to start descending the list from */ function ascendList(Data storage self, uint256 _key, address _startId) private view returns (address, address) { // If `_startId` is the tail, check if the insert position is after the tail if (self.tail == _startId && _key <= self.nodes[_startId].key) { return (_startId, address(0)); } address nextId = _startId; address prevId = self.nodes[nextId].prevId; // Ascend the list until we reach the end or until we find a valid insertion point while (nextId != address(0) && !validInsertPosition(self, _key, prevId, nextId)) { nextId = self.nodes[nextId].prevId; prevId = self.nodes[nextId].prevId; } return (prevId, nextId); } /* * @dev Find the insert position for a new node with the given key * @param _key Node's key * @param _prevId Id of previous node for the insert position * @param _nextId Id of next node for the insert position */ function findInsertPosition(Data storage self, uint256 _key, address _prevId, address _nextId) private view returns (address, address) { address prevId = _prevId; address nextId = _nextId; if (prevId != address(0)) { if (!contains(self, prevId) || _key > self.nodes[prevId].key) { // `prevId` does not exist anymore or now has a smaller key than the given key prevId = address(0); } } if (nextId != address(0)) { if (!contains(self, nextId) || _key < self.nodes[nextId].key) { // `nextId` does not exist anymore or now has a larger key than the given key nextId = address(0); } } if (prevId == address(0) && nextId == address(0)) { // No hint - descend list starting from head return descendList(self, _key, self.head); } else if (prevId == address(0)) { // No `prevId` for hint - ascend list starting from `nextId` return ascendList(self, _key, nextId); } else if (nextId == address(0)) { // No `nextId` for hint - descend list starting from `prevId` return descendList(self, _key, prevId); } else { // Descend list starting from `prevId` return descendList(self, _key, prevId); } } } library EarningsPool { using SafeMath for uint256; // Represents rewards and fees to be distributed to delegators struct Data { uint256 rewardPool; // Rewards in the pool uint256 feePool; // Fees in the pool uint256 totalStake; // Transcoder's total stake during the pool's round uint256 claimableStake; // Stake that can be used to claim portions of the fee and reward pool uint256 transcoderRewardCut; // Reward cut for the reward pool uint256 transcoderFeeShare; // Fee share for the fee pool } function init(EarningsPool.Data storage earningsPool, uint256 _stake, uint256 _rewardCut, uint256 _feeShare) internal { earningsPool.totalStake = _stake; earningsPool.claimableStake = _stake; earningsPool.transcoderRewardCut = _rewardCut; earningsPool.transcoderFeeShare = _feeShare; } function hasClaimableShares(EarningsPool.Data storage earningsPool) internal view returns (bool) { return earningsPool.claimableStake > 0; } function claimShare(EarningsPool.Data storage earningsPool, uint256 _stake, bool _isTranscoder) internal returns (uint256, uint256) { uint256 fees = 0; uint256 rewards = 0; if (earningsPool.feePool > 0) { // Compute fee share fees = feePoolShare(earningsPool, _stake, _isTranscoder); earningsPool.feePool = earningsPool.feePool.sub(fees); } if (earningsPool.rewardPool > 0) { // Compute reward share rewards = rewardPoolShare(earningsPool, _stake, _isTranscoder); earningsPool.rewardPool = earningsPool.rewardPool.sub(rewards); } // Update remaning claimable stake for token pools earningsPool.claimableStake = earningsPool.claimableStake.sub(_stake); return (fees, rewards); } function feePoolShare(EarningsPool.Data storage earningsPool, uint256 _stake, bool _isTranscoder) internal view returns (uint256) { uint256 transcoderFees = 0; uint256 delegatorFees = 0; if (earningsPool.claimableStake > 0) { uint256 delegatorsFees = MathUtils.percOf(earningsPool.feePool, earningsPool.transcoderFeeShare); transcoderFees = earningsPool.feePool.sub(delegatorsFees); delegatorFees = MathUtils.percOf(delegatorsFees, _stake, earningsPool.claimableStake); } if (_isTranscoder) { return delegatorFees.add(transcoderFees); } else { return delegatorFees; } } function rewardPoolShare(EarningsPool.Data storage earningsPool, uint256 _stake, bool _isTranscoder) internal view returns (uint256) { uint256 transcoderRewards = 0; uint256 delegatorRewards = 0; if (earningsPool.claimableStake > 0) { transcoderRewards = MathUtils.percOf(earningsPool.rewardPool, earningsPool.transcoderRewardCut); delegatorRewards = MathUtils.percOf(earningsPool.rewardPool.sub(transcoderRewards), _stake, earningsPool.claimableStake); } if (_isTranscoder) { return delegatorRewards.add(transcoderRewards); } else { return delegatorRewards; } } } contract ILivepeerToken is ERC20, Ownable { function mint(address _to, uint256 _amount) public returns (bool); function burn(uint256 _amount) public; } /** * @title Minter interface */ contract IMinter { // Events event SetCurrentRewardTokens(uint256 currentMintableTokens, uint256 currentInflation); // External functions function createReward(uint256 _fracNum, uint256 _fracDenom) external returns (uint256); function trustedTransferTokens(address _to, uint256 _amount) external; function trustedBurnTokens(uint256 _amount) external; function trustedWithdrawETH(address _to, uint256 _amount) external; function depositETH() external payable returns (bool); function setCurrentRewardTokens() external; // Public functions function getController() public view returns (IController); } /** * @title RoundsManager interface */ contract IRoundsManager { // Events event NewRound(uint256 round); // External functions function initializeRound() external; // Public functions function blockNum() public view returns (uint256); function blockHash(uint256 _block) public view returns (bytes32); function currentRound() public view returns (uint256); function currentRoundStartBlock() public view returns (uint256); function currentRoundInitialized() public view returns (bool); function currentRoundLocked() public view returns (bool); } /* * @title Interface for BondingManager */ contract IBondingManager { event TranscoderUpdate(address indexed transcoder, uint256 pendingRewardCut, uint256 pendingFeeShare, uint256 pendingPricePerSegment, bool registered); event TranscoderEvicted(address indexed transcoder); event TranscoderResigned(address indexed transcoder); event TranscoderSlashed(address indexed transcoder, address finder, uint256 penalty, uint256 finderReward); event Reward(address indexed transcoder, uint256 amount); event Bond(address indexed delegate, address indexed delegator); event Unbond(address indexed delegate, address indexed delegator); event WithdrawStake(address indexed delegator); event WithdrawFees(address indexed delegator); // External functions function setActiveTranscoders() external; function updateTranscoderWithFees(address _transcoder, uint256 _fees, uint256 _round) external; function slashTranscoder(address _transcoder, address _finder, uint256 _slashAmount, uint256 _finderFee) external; function electActiveTranscoder(uint256 _maxPricePerSegment, bytes32 _blockHash, uint256 _round) external view returns (address); // Public functions function transcoderTotalStake(address _transcoder) public view returns (uint256); function activeTranscoderTotalStake(address _transcoder, uint256 _round) public view returns (uint256); function isRegisteredTranscoder(address _transcoder) public view returns (bool); function getTotalBonded() public view returns (uint256); } /** * @title BondingManager * @dev Manages bonding, transcoder and rewards/fee accounting related operations of the Livepeer protocol */ contract BondingManager is ManagerProxyTarget, IBondingManager { using SafeMath for uint256; using SortedDoublyLL for SortedDoublyLL.Data; using EarningsPool for EarningsPool.Data; // Time between unbonding and possible withdrawl in rounds uint64 public unbondingPeriod; // Number of active transcoders uint256 public numActiveTranscoders; // Max number of rounds that a caller can claim earnings for at once uint256 public maxEarningsClaimsRounds; // Represents a transcoder's current state struct Transcoder { uint256 lastRewardRound; // Last round that the transcoder called reward uint256 rewardCut; // % of reward paid to transcoder by a delegator uint256 feeShare; // % of fees paid to delegators by transcoder uint256 pricePerSegment; // Price per segment (denominated in LPT units) for a stream uint256 pendingRewardCut; // Pending reward cut for next round if the transcoder is active uint256 pendingFeeShare; // Pending fee share for next round if the transcoder is active uint256 pendingPricePerSegment; // Pending price per segment for next round if the transcoder is active mapping (uint256 => EarningsPool.Data) earningsPoolPerRound; // Mapping of round => earnings pool for the round } // The various states a transcoder can be in enum TranscoderStatus { NotRegistered, Registered } // Represents a delegator's current state struct Delegator { uint256 bondedAmount; // The amount of bonded tokens uint256 fees; // The amount of fees collected address delegateAddress; // The address delegated to uint256 delegatedAmount; // The amount of tokens delegated to the delegator uint256 startRound; // The round the delegator transitions to bonded phase and is delegated to someone uint256 withdrawRound; // The round at which a delegator can withdraw uint256 lastClaimRound; // The last round during which the delegator claimed its earnings } // The various states a delegator can be in enum DelegatorStatus { Pending, Bonded, Unbonding, Unbonded } // Keep track of the known transcoders and delegators mapping (address => Delegator) private delegators; mapping (address => Transcoder) private transcoders; // Keep track of total bonded tokens uint256 private totalBonded; // Candidate and reserve transcoders SortedDoublyLL.Data private transcoderPool; // Represents the active transcoder set struct ActiveTranscoderSet { address[] transcoders; mapping (address => bool) isActive; uint256 totalStake; } // Keep track of active transcoder set for each round mapping (uint256 => ActiveTranscoderSet) public activeTranscoderSet; // Check if sender is JobsManager modifier onlyJobsManager() { require(msg.sender == controller.getContract(keccak256("JobsManager"))); _; } // Check if sender is RoundsManager modifier onlyRoundsManager() { require(msg.sender == controller.getContract(keccak256("RoundsManager"))); _; } // Check if current round is initialized modifier currentRoundInitialized() { require(roundsManager().currentRoundInitialized()); _; } // Automatically claim earnings from lastClaimRound through the current round modifier autoClaimEarnings() { updateDelegatorWithEarnings(msg.sender, roundsManager().currentRound()); _; } /** * @dev BondingManager constructor. Only invokes constructor of base Manager contract with provided Controller address * @param _controller Address of Controller that this contract will be registered with */ function BondingManager(address _controller) public Manager(_controller) {} /** * @dev Set unbonding period. Only callable by Controller owner * @param _unbondingPeriod Rounds between unbonding and possible withdrawal */ function setUnbondingPeriod(uint64 _unbondingPeriod) external onlyControllerOwner { unbondingPeriod = _unbondingPeriod; ParameterUpdate("unbondingPeriod"); } /** * @dev Set max number of registered transcoders. Only callable by Controller owner * @param _numTranscoders Max number of registered transcoders */ function setNumTranscoders(uint256 _numTranscoders) external onlyControllerOwner { // Max number of transcoders must be greater than or equal to number of active transcoders require(_numTranscoders >= numActiveTranscoders); transcoderPool.setMaxSize(_numTranscoders); ParameterUpdate("numTranscoders"); } /** * @dev Set number of active transcoders. Only callable by Controller owner * @param _numActiveTranscoders Number of active transcoders */ function setNumActiveTranscoders(uint256 _numActiveTranscoders) external onlyControllerOwner { // Number of active transcoders cannot exceed max number of transcoders require(_numActiveTranscoders <= transcoderPool.getMaxSize()); numActiveTranscoders = _numActiveTranscoders; ParameterUpdate("numActiveTranscoders"); } /** * @dev Set max number of rounds a caller can claim earnings for at once. Only callable by Controller owner * @param _maxEarningsClaimsRounds Max number of rounds a caller can claim earnings for at once */ function setMaxEarningsClaimsRounds(uint256 _maxEarningsClaimsRounds) external onlyControllerOwner { maxEarningsClaimsRounds = _maxEarningsClaimsRounds; ParameterUpdate("maxEarningsClaimsRounds"); } /** * @dev The sender is declaring themselves as a candidate for active transcoding. * @param _rewardCut % of reward paid to transcoder by a delegator * @param _feeShare % of fees paid to delegators by a transcoder * @param _pricePerSegment Price per segment (denominated in Wei) for a stream */ function transcoder(uint256 _rewardCut, uint256 _feeShare, uint256 _pricePerSegment) external whenSystemNotPaused currentRoundInitialized { Transcoder storage t = transcoders[msg.sender]; Delegator storage del = delegators[msg.sender]; if (roundsManager().currentRoundLocked()) { // If it is the lock period of the current round // the lowest price previously set by any transcoder // becomes the price floor and the caller can lower its // own price to a point greater than or equal to the price floor // Caller must already be a registered transcoder require(transcoderStatus(msg.sender) == TranscoderStatus.Registered); // Provided rewardCut value must equal the current pendingRewardCut value // This value cannot change during the lock period require(_rewardCut == t.pendingRewardCut); // Provided feeShare value must equal the current pendingFeeShare value // This value cannot change during the lock period require(_feeShare == t.pendingFeeShare); // Iterate through the transcoder pool to find the price floor // Since the caller must be a registered transcoder, the transcoder pool size will always at least be 1 // Thus, we can safely set the initial price floor to be the pendingPricePerSegment of the first // transcoder in the pool address currentTranscoder = transcoderPool.getFirst(); uint256 priceFloor = transcoders[currentTranscoder].pendingPricePerSegment; for (uint256 i = 0; i < transcoderPool.getSize(); i++) { if (transcoders[currentTranscoder].pendingPricePerSegment < priceFloor) { priceFloor = transcoders[currentTranscoder].pendingPricePerSegment; } currentTranscoder = transcoderPool.getNext(currentTranscoder); } // Provided pricePerSegment must be greater than or equal to the price floor and // less than or equal to the previously set pricePerSegment by the caller require(_pricePerSegment >= priceFloor && _pricePerSegment <= t.pendingPricePerSegment); t.pendingPricePerSegment = _pricePerSegment; TranscoderUpdate(msg.sender, t.pendingRewardCut, t.pendingFeeShare, _pricePerSegment, true); } else { // It is not the lock period of the current round // Caller is free to change rewardCut, feeShare, pricePerSegment as it pleases // If caller is not a registered transcoder, it can also register and join the transcoder pool // if it has sufficient delegated stake // If caller is not a registered transcoder and does not have sufficient delegated stake // to join the transcoder pool, it can change rewardCut, feeShare, pricePerSegment // as information signals to delegators in an effort to camapaign and accumulate // more delegated stake // Reward cut must be a valid percentage require(MathUtils.validPerc(_rewardCut)); // Fee share must be a valid percentage require(MathUtils.validPerc(_feeShare)); // Must have a non-zero amount bonded to self require(del.delegateAddress == msg.sender && del.bondedAmount > 0); t.pendingRewardCut = _rewardCut; t.pendingFeeShare = _feeShare; t.pendingPricePerSegment = _pricePerSegment; uint256 delegatedAmount = del.delegatedAmount; // Check if transcoder is not already registered if (transcoderStatus(msg.sender) == TranscoderStatus.NotRegistered) { if (!transcoderPool.isFull()) { // If pool is not full add new transcoder transcoderPool.insert(msg.sender, delegatedAmount, address(0), address(0)); } else { address lastTranscoder = transcoderPool.getLast(); if (delegatedAmount > transcoderPool.getKey(lastTranscoder)) { // If pool is full and caller has more delegated stake than the transcoder in the pool with the least delegated stake: // - Evict transcoder in pool with least delegated stake // - Add caller to pool transcoderPool.remove(lastTranscoder); transcoderPool.insert(msg.sender, delegatedAmount, address(0), address(0)); TranscoderEvicted(lastTranscoder); } } } TranscoderUpdate(msg.sender, _rewardCut, _feeShare, _pricePerSegment, transcoderPool.contains(msg.sender)); } } /** * @dev Delegate stake towards a specific address. * @param _amount The amount of LPT to stake. * @param _to The address of the transcoder to stake towards. */ function bond( uint256 _amount, address _to ) external whenSystemNotPaused currentRoundInitialized autoClaimEarnings { Delegator storage del = delegators[msg.sender]; uint256 currentRound = roundsManager().currentRound(); // Amount to delegate uint256 delegationAmount = _amount; if (delegatorStatus(msg.sender) == DelegatorStatus.Unbonded || delegatorStatus(msg.sender) == DelegatorStatus.Unbonding) { // New delegate // Set start round // Don't set start round if delegator is in pending state because the start round would not change del.startRound = currentRound.add(1); // If transitioning from unbonding or unbonded state // make sure to zero out withdraw round del.withdrawRound = 0; // Unbonded or unbonding state = no existing delegate // Thus, delegation amount = bonded stake + provided amount // If caller is bonding for the first time or withdrew previously bonded stake, delegation amount = provided amount delegationAmount = delegationAmount.add(del.bondedAmount); } else if (del.delegateAddress != address(0) && _to != del.delegateAddress) { // A registered transcoder cannot delegate its bonded stake toward another address // because it can only be delegated toward itself // In the future, if delegation towards another registered transcoder as an already // registered transcoder becomes useful (i.e. for transitive delegation), this restriction // could be removed require(transcoderStatus(msg.sender) == TranscoderStatus.NotRegistered); // Changing delegate // Set start round del.startRound = currentRound.add(1); // Update amount to delegate with previous delegation amount delegationAmount = delegationAmount.add(del.bondedAmount); // Decrease old delegate's delegated amount delegators[del.delegateAddress].delegatedAmount = delegators[del.delegateAddress].delegatedAmount.sub(del.bondedAmount); if (transcoderStatus(del.delegateAddress) == TranscoderStatus.Registered) { // Previously delegated to a transcoder // Decrease old transcoder's total stake transcoderPool.updateKey(del.delegateAddress, transcoderPool.getKey(del.delegateAddress).sub(del.bondedAmount), address(0), address(0)); } } // Delegation amount must be > 0 - cannot delegate to someone without having bonded stake require(delegationAmount > 0); // Update delegate del.delegateAddress = _to; // Update current delegate's delegated amount with delegation amount delegators[_to].delegatedAmount = delegators[_to].delegatedAmount.add(delegationAmount); if (transcoderStatus(_to) == TranscoderStatus.Registered) { // Delegated to a transcoder // Increase transcoder's total stake transcoderPool.updateKey(_to, transcoderPool.getKey(del.delegateAddress).add(delegationAmount), address(0), address(0)); } if (_amount > 0) { // Update bonded amount del.bondedAmount = del.bondedAmount.add(_amount); // Update total bonded tokens totalBonded = totalBonded.add(_amount); // Transfer the LPT to the Minter livepeerToken().transferFrom(msg.sender, minter(), _amount); } Bond(_to, msg.sender); } /** * @dev Unbond delegator's current stake. Delegator enters unbonding state */ function unbond() external whenSystemNotPaused currentRoundInitialized autoClaimEarnings { // Sender must be in bonded state require(delegatorStatus(msg.sender) == DelegatorStatus.Bonded); Delegator storage del = delegators[msg.sender]; uint256 currentRound = roundsManager().currentRound(); // Transition to unbonding phase del.withdrawRound = currentRound.add(unbondingPeriod); // Decrease delegate's delegated amount delegators[del.delegateAddress].delegatedAmount = delegators[del.delegateAddress].delegatedAmount.sub(del.bondedAmount); // Update total bonded tokens totalBonded = totalBonded.sub(del.bondedAmount); if (transcoderStatus(msg.sender) == TranscoderStatus.Registered) { // If caller is a registered transcoder, resign // In the future, with partial unbonding there would be a check for 0 bonded stake as well resignTranscoder(msg.sender); } if (del.delegateAddress != msg.sender && transcoderStatus(del.delegateAddress) == TranscoderStatus.Registered) { // If delegate is not self and is a registered transcoder, decrease its delegated stake // We do not need to decrease delegated stake if delegate is self because we would have already removed self // from the transcoder pool transcoderPool.updateKey(del.delegateAddress, transcoderPool.getKey(del.delegateAddress).sub(del.bondedAmount), address(0), address(0)); } // Delegator no longer bonded to anyone del.delegateAddress = address(0); // Unbonding delegator does not have a start round del.startRound = 0; Unbond(del.delegateAddress, msg.sender); } /** * @dev Withdraws bonded stake to the caller after unbonding period. */ function withdrawStake() external whenSystemNotPaused currentRoundInitialized { // Delegator must be in the unbonded state require(delegatorStatus(msg.sender) == DelegatorStatus.Unbonded); uint256 amount = delegators[msg.sender].bondedAmount; delegators[msg.sender].bondedAmount = 0; delegators[msg.sender].withdrawRound = 0; // Tell Minter to transfer stake (LPT) to the delegator minter().trustedTransferTokens(msg.sender, amount); WithdrawStake(msg.sender); } /** * @dev Withdraws fees to the caller */ function withdrawFees() external whenSystemNotPaused currentRoundInitialized autoClaimEarnings { // Delegator must have fees require(delegators[msg.sender].fees > 0); uint256 amount = delegators[msg.sender].fees; delegators[msg.sender].fees = 0; // Tell Minter to transfer fees (ETH) to the delegator minter().trustedWithdrawETH(msg.sender, amount); WithdrawFees(msg.sender); } /** * @dev Set active transcoder set for the current round */ function setActiveTranscoders() external whenSystemNotPaused onlyRoundsManager { uint256 currentRound = roundsManager().currentRound(); uint256 activeSetSize = Math.min256(numActiveTranscoders, transcoderPool.getSize()); uint256 totalStake = 0; address currentTranscoder = transcoderPool.getFirst(); for (uint256 i = 0; i < activeSetSize; i++) { activeTranscoderSet[currentRound].transcoders.push(currentTranscoder); activeTranscoderSet[currentRound].isActive[currentTranscoder] = true; uint256 stake = transcoderPool.getKey(currentTranscoder); uint256 rewardCut = transcoders[currentTranscoder].pendingRewardCut; uint256 feeShare = transcoders[currentTranscoder].pendingFeeShare; uint256 pricePerSegment = transcoders[currentTranscoder].pendingPricePerSegment; Transcoder storage t = transcoders[currentTranscoder]; // Set pending rates as current rates t.rewardCut = rewardCut; t.feeShare = feeShare; t.pricePerSegment = pricePerSegment; // Initialize token pool t.earningsPoolPerRound[currentRound].init(stake, rewardCut, feeShare); totalStake = totalStake.add(stake); // Get next transcoder in the pool currentTranscoder = transcoderPool.getNext(currentTranscoder); } // Update total stake of all active transcoders activeTranscoderSet[currentRound].totalStake = totalStake; } /** * @dev Distribute the token rewards to transcoder and delegates. * Active transcoders call this once per cycle when it is their turn. */ function reward() external whenSystemNotPaused currentRoundInitialized { uint256 currentRound = roundsManager().currentRound(); // Sender must be an active transcoder require(activeTranscoderSet[currentRound].isActive[msg.sender]); // Transcoder must not have called reward for this round already require(transcoders[msg.sender].lastRewardRound != currentRound); // Set last round that transcoder called reward transcoders[msg.sender].lastRewardRound = currentRound; // Create reward based on active transcoder's stake relative to the total active stake // rewardTokens = (current mintable tokens for the round * active transcoder stake) / total active stake uint256 rewardTokens = minter().createReward(activeTranscoderTotalStake(msg.sender, currentRound), activeTranscoderSet[currentRound].totalStake); updateTranscoderWithRewards(msg.sender, rewardTokens, currentRound); Reward(msg.sender, rewardTokens); } /** * @dev Update transcoder's fee pool * @param _transcoder Transcoder address * @param _fees Fees from verified job claims */ function updateTranscoderWithFees( address _transcoder, uint256 _fees, uint256 _round ) external whenSystemNotPaused onlyJobsManager { // Transcoder must be registered require(transcoderStatus(_transcoder) == TranscoderStatus.Registered); Transcoder storage t = transcoders[_transcoder]; EarningsPool.Data storage earningsPool = t.earningsPoolPerRound[_round]; // Add fees to fee pool earningsPool.feePool = earningsPool.feePool.add(_fees); } /** * @dev Slash a transcoder. Slashing can be invoked by the protocol or a finder. * @param _transcoder Transcoder address * @param _finder Finder that proved a transcoder violated a slashing condition. Null address if there is no finder * @param _slashAmount Percentage of transcoder bond to be slashed * @param _finderFee Percentage of penalty awarded to finder. Zero if there is no finder */ function slashTranscoder( address _transcoder, address _finder, uint256 _slashAmount, uint256 _finderFee ) external whenSystemNotPaused onlyJobsManager { Delegator storage del = delegators[_transcoder]; if (del.bondedAmount > 0) { uint256 penalty = MathUtils.percOf(delegators[_transcoder].bondedAmount, _slashAmount); // Decrease bonded stake del.bondedAmount = del.bondedAmount.sub(penalty); // If still bonded // - Decrease delegate's delegated amount // - Decrease total bonded tokens if (delegatorStatus(_transcoder) == DelegatorStatus.Bonded) { delegators[del.delegateAddress].delegatedAmount = delegators[del.delegateAddress].delegatedAmount.sub(penalty); totalBonded = totalBonded.sub(penalty); } // If registered transcoder, resign it if (transcoderStatus(_transcoder) == TranscoderStatus.Registered) { resignTranscoder(_transcoder); } // Account for penalty uint256 burnAmount = penalty; // Award finder fee if there is a finder address if (_finder != address(0)) { uint256 finderAmount = MathUtils.percOf(penalty, _finderFee); minter().trustedTransferTokens(_finder, finderAmount); // Minter burns the slashed funds - finder reward minter().trustedBurnTokens(burnAmount.sub(finderAmount)); TranscoderSlashed(_transcoder, _finder, penalty, finderAmount); } else { // Minter burns the slashed funds minter().trustedBurnTokens(burnAmount); TranscoderSlashed(_transcoder, address(0), penalty, 0); } } else { TranscoderSlashed(_transcoder, _finder, 0, 0); } } /** * @dev Pseudorandomly elect a currently active transcoder that charges a price per segment less than or equal to the max price per segment for a job * Returns address of elected active transcoder and its price per segment * @param _maxPricePerSegment Max price (in LPT base units) per segment of a stream * @param _blockHash Job creation block hash used as a pseudorandom seed for assigning an active transcoder * @param _round Job creation round */ function electActiveTranscoder(uint256 _maxPricePerSegment, bytes32 _blockHash, uint256 _round) external view returns (address) { uint256 activeSetSize = activeTranscoderSet[_round].transcoders.length; // Create array to store available transcoders charging an acceptable price per segment address[] memory availableTranscoders = new address[](activeSetSize); // Keep track of the actual number of available transcoders uint256 numAvailableTranscoders = 0; // Keep track of total stake of available transcoders uint256 totalAvailableTranscoderStake = 0; for (uint256 i = 0; i < activeSetSize; i++) { address activeTranscoder = activeTranscoderSet[_round].transcoders[i]; // If a transcoder is active and charges an acceptable price per segment add it to the array of available transcoders if (activeTranscoderSet[_round].isActive[activeTranscoder] && transcoders[activeTranscoder].pricePerSegment <= _maxPricePerSegment) { availableTranscoders[numAvailableTranscoders] = activeTranscoder; numAvailableTranscoders++; totalAvailableTranscoderStake = totalAvailableTranscoderStake.add(activeTranscoderTotalStake(activeTranscoder, _round)); } } if (numAvailableTranscoders == 0) { // There is no currently available transcoder that charges a price per segment less than or equal to the max price per segment for a job return address(0); } else { // Pseudorandomly pick an available transcoder weighted by its stake relative to the total stake of all available transcoders uint256 r = uint256(_blockHash) % totalAvailableTranscoderStake; uint256 s = 0; uint256 j = 0; while (s <= r && j < numAvailableTranscoders) { s = s.add(activeTranscoderTotalStake(availableTranscoders[j], _round)); j++; } return availableTranscoders[j - 1]; } } /** * @dev Claim token pools shares for a delegator from its lastClaimRound through the end round * @param _endRound The last round for which to claim token pools shares for a delegator */ function claimEarnings(uint256 _endRound) external whenSystemNotPaused currentRoundInitialized { // End round must be after the last claim round require(delegators[msg.sender].lastClaimRound < _endRound); // End round must not be after the current round require(_endRound <= roundsManager().currentRound()); updateDelegatorWithEarnings(msg.sender, _endRound); } /** * @dev Returns pending bonded stake for a delegator from its lastClaimRound through an end round * @param _delegator Address of delegator * @param _endRound The last round to compute pending stake from */ function pendingStake(address _delegator, uint256 _endRound) public view returns (uint256) { uint256 currentRound = roundsManager().currentRound(); Delegator storage del = delegators[_delegator]; // End round must be before or equal to current round and after lastClaimRound require(_endRound <= currentRound && _endRound > del.lastClaimRound); uint256 currentBondedAmount = del.bondedAmount; for (uint256 i = del.lastClaimRound + 1; i <= _endRound; i++) { EarningsPool.Data storage earningsPool = transcoders[del.delegateAddress].earningsPoolPerRound[i]; bool isTranscoder = _delegator == del.delegateAddress; if (earningsPool.hasClaimableShares()) { // Calculate and add reward pool share from this round currentBondedAmount = currentBondedAmount.add(earningsPool.rewardPoolShare(currentBondedAmount, isTranscoder)); } } return currentBondedAmount; } /** * @dev Returns pending fees for a delegator from its lastClaimRound through an end round * @param _delegator Address of delegator * @param _endRound The last round to compute pending fees from */ function pendingFees(address _delegator, uint256 _endRound) public view returns (uint256) { uint256 currentRound = roundsManager().currentRound(); Delegator storage del = delegators[_delegator]; // End round must be before or equal to current round and after lastClaimRound require(_endRound <= currentRound && _endRound > del.lastClaimRound); uint256 currentFees = del.fees; uint256 currentBondedAmount = del.bondedAmount; for (uint256 i = del.lastClaimRound + 1; i <= _endRound; i++) { EarningsPool.Data storage earningsPool = transcoders[del.delegateAddress].earningsPoolPerRound[i]; if (earningsPool.hasClaimableShares()) { bool isTranscoder = _delegator == del.delegateAddress; // Calculate and add fee pool share from this round currentFees = currentFees.add(earningsPool.feePoolShare(currentBondedAmount, isTranscoder)); // Calculate new bonded amount with rewards from this round. Updated bonded amount used // to calculate fee pool share in next round currentBondedAmount = currentBondedAmount.add(earningsPool.rewardPoolShare(currentBondedAmount, isTranscoder)); } } return currentFees; } /** * @dev Returns total bonded stake for an active transcoder * @param _transcoder Address of a transcoder */ function activeTranscoderTotalStake(address _transcoder, uint256 _round) public view returns (uint256) { // Must be active transcoder require(activeTranscoderSet[_round].isActive[_transcoder]); return transcoders[_transcoder].earningsPoolPerRound[_round].totalStake; } /** * @dev Returns total bonded stake for a transcoder * @param _transcoder Address of transcoder */ function transcoderTotalStake(address _transcoder) public view returns (uint256) { return transcoderPool.getKey(_transcoder); } /* * @dev Computes transcoder status * @param _transcoder Address of transcoder */ function transcoderStatus(address _transcoder) public view returns (TranscoderStatus) { if (transcoderPool.contains(_transcoder)) { return TranscoderStatus.Registered; } else { return TranscoderStatus.NotRegistered; } } /** * @dev Computes delegator status * @param _delegator Address of delegator */ function delegatorStatus(address _delegator) public view returns (DelegatorStatus) { Delegator storage del = delegators[_delegator]; if (del.withdrawRound > 0) { // Delegator called unbond if (roundsManager().currentRound() >= del.withdrawRound) { return DelegatorStatus.Unbonded; } else { return DelegatorStatus.Unbonding; } } else if (del.startRound > roundsManager().currentRound()) { // Delegator round start is in the future return DelegatorStatus.Pending; } else if (del.startRound > 0 && del.startRound <= roundsManager().currentRound()) { // Delegator round start is now or in the past return DelegatorStatus.Bonded; } else { // Default to unbonded return DelegatorStatus.Unbonded; } } /** * @dev Return transcoder information * @param _transcoder Address of transcoder */ function getTranscoder( address _transcoder ) public view returns (uint256 lastRewardRound, uint256 rewardCut, uint256 feeShare, uint256 pricePerSegment, uint256 pendingRewardCut, uint256 pendingFeeShare, uint256 pendingPricePerSegment) { Transcoder storage t = transcoders[_transcoder]; lastRewardRound = t.lastRewardRound; rewardCut = t.rewardCut; feeShare = t.feeShare; pricePerSegment = t.pricePerSegment; pendingRewardCut = t.pendingRewardCut; pendingFeeShare = t.pendingFeeShare; pendingPricePerSegment = t.pendingPricePerSegment; } /** * @dev Return transcoder's token pools for a given round * @param _transcoder Address of transcoder * @param _round Round number */ function getTranscoderEarningsPoolForRound( address _transcoder, uint256 _round ) public view returns (uint256 rewardPool, uint256 feePool, uint256 totalStake, uint256 claimableStake) { EarningsPool.Data storage earningsPool = transcoders[_transcoder].earningsPoolPerRound[_round]; rewardPool = earningsPool.rewardPool; feePool = earningsPool.feePool; totalStake = earningsPool.totalStake; claimableStake = earningsPool.claimableStake; } /** * @dev Return delegator info * @param _delegator Address of delegator */ function getDelegator( address _delegator ) public view returns (uint256 bondedAmount, uint256 fees, address delegateAddress, uint256 delegatedAmount, uint256 startRound, uint256 withdrawRound, uint256 lastClaimRound) { Delegator storage del = delegators[_delegator]; bondedAmount = del.bondedAmount; fees = del.fees; delegateAddress = del.delegateAddress; delegatedAmount = del.delegatedAmount; startRound = del.startRound; withdrawRound = del.withdrawRound; lastClaimRound = del.lastClaimRound; } /** * @dev Returns max size of transcoder pool */ function getTranscoderPoolMaxSize() public view returns (uint256) { return transcoderPool.getMaxSize(); } /** * @dev Returns size of transcoder pool */ function getTranscoderPoolSize() public view returns (uint256) { return transcoderPool.getSize(); } /** * @dev Returns transcoder with most stake in pool */ function getFirstTranscoderInPool() public view returns (address) { return transcoderPool.getFirst(); } /** * @dev Returns next transcoder in pool for a given transcoder * @param _transcoder Address of a transcoder in the pool */ function getNextTranscoderInPool(address _transcoder) public view returns (address) { return transcoderPool.getNext(_transcoder); } /** * @dev Return total bonded tokens */ function getTotalBonded() public view returns (uint256) { return totalBonded; } /** * @dev Return total active stake for a round * @param _round Round number */ function getTotalActiveStake(uint256 _round) public view returns (uint256) { return activeTranscoderSet[_round].totalStake; } /** * @dev Return whether a transcoder was active during a round * @param _transcoder Transcoder address * @param _round Round number */ function isActiveTranscoder(address _transcoder, uint256 _round) public view returns (bool) { return activeTranscoderSet[_round].isActive[_transcoder]; } /** * @dev Return whether a transcoder is registered * @param _transcoder Transcoder address */ function isRegisteredTranscoder(address _transcoder) public view returns (bool) { return transcoderStatus(_transcoder) == TranscoderStatus.Registered; } /** * @dev Remove transcoder */ function resignTranscoder(address _transcoder) internal { uint256 currentRound = roundsManager().currentRound(); if (activeTranscoderSet[currentRound].isActive[_transcoder]) { // Decrease total active stake for the round activeTranscoderSet[currentRound].totalStake = activeTranscoderSet[currentRound].totalStake.sub(activeTranscoderTotalStake(_transcoder, currentRound)); // Set transcoder as inactive activeTranscoderSet[currentRound].isActive[_transcoder] = false; } // Remove transcoder from pools transcoderPool.remove(_transcoder); TranscoderResigned(_transcoder); } /** * @dev Update a transcoder with rewards * @param _transcoder Address of transcoder * @param _rewards Amount of rewards * @param _round Round that transcoder is updated */ function updateTranscoderWithRewards(address _transcoder, uint256 _rewards, uint256 _round) internal { Transcoder storage t = transcoders[_transcoder]; Delegator storage del = delegators[_transcoder]; EarningsPool.Data storage earningsPool = t.earningsPoolPerRound[_round]; // Add rewards to reward pool earningsPool.rewardPool = earningsPool.rewardPool.add(_rewards); // Update transcoder's delegated amount with rewards del.delegatedAmount = del.delegatedAmount.add(_rewards); // Update transcoder's total stake with rewards uint256 newStake = transcoderPool.getKey(_transcoder).add(_rewards); transcoderPool.updateKey(_transcoder, newStake, address(0), address(0)); // Update total bonded tokens with claimable rewards totalBonded = totalBonded.add(_rewards); } /** * @dev Update a delegator with token pools shares from its lastClaimRound through a given round * @param _delegator Delegator address * @param _endRound The last round for which to update a delegator's stake with token pools shares */ function updateDelegatorWithEarnings(address _delegator, uint256 _endRound) internal { Delegator storage del = delegators[_delegator]; // Only will have earnings to claim if you have a delegate // If not delegated, skip the earnings claim process if (del.delegateAddress != address(0)) { // Cannot claim earnings for more than maxEarningsClaimsRounds // This is a number to cause transactions to fail early if // we know they will require too much gas to loop through all the necessary rounds to claim earnings // The user should instead manually invoke `claimEarnings` to split up the claiming process // across multiple transactions require(_endRound.sub(del.lastClaimRound) <= maxEarningsClaimsRounds); uint256 currentBondedAmount = del.bondedAmount; uint256 currentFees = del.fees; for (uint256 i = del.lastClaimRound + 1; i <= _endRound; i++) { EarningsPool.Data storage earningsPool = transcoders[del.delegateAddress].earningsPoolPerRound[i]; if (earningsPool.hasClaimableShares()) { bool isTranscoder = _delegator == del.delegateAddress; var (fees, rewards) = earningsPool.claimShare(currentBondedAmount, isTranscoder); currentFees = currentFees.add(fees); currentBondedAmount = currentBondedAmount.add(rewards); } } // Rewards are bonded by default del.bondedAmount = currentBondedAmount; del.fees = currentFees; } del.lastClaimRound = _endRound; } /** * @dev Return LivepeerToken interface */ function livepeerToken() internal view returns (ILivepeerToken) { return ILivepeerToken(controller.getContract(keccak256("LivepeerToken"))); } /** * @dev Return Minter interface */ function minter() internal view returns (IMinter) { return IMinter(controller.getContract(keccak256("Minter"))); } /** * @dev Return RoundsManager interface */ function roundsManager() internal view returns (IRoundsManager) { return IRoundsManager(controller.getContract(keccak256("RoundsManager"))); } }
Contract Security Audit
- 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":"delegatorStatus","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"reward","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_transcoder","type":"address"},{"name":"_finder","type":"address"},{"name":"_slashAmount","type":"uint256"},{"name":"_finderFee","type":"uint256"}],"name":"slashTranscoder","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"}],"name":"getNextTranscoderInPool","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"setActiveTranscoders","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"},{"name":"_round","type":"uint256"}],"name":"getTranscoderEarningsPoolForRound","outputs":[{"name":"rewardPool","type":"uint256"},{"name":"feePool","type":"uint256"},{"name":"totalStake","type":"uint256"},{"name":"claimableStake","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_endRound","type":"uint256"}],"name":"claimEarnings","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTranscoderPoolSize","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_transcoder","type":"address"},{"name":"_fees","type":"uint256"},{"name":"_round","type":"uint256"}],"name":"updateTranscoderWithFees","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"activeTranscoderSet","outputs":[{"name":"totalStake","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdrawFees","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"targetContractId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTranscoderPoolMaxSize","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalBonded","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"}],"name":"getTranscoder","outputs":[{"name":"lastRewardRound","type":"uint256"},{"name":"rewardCut","type":"uint256"},{"name":"feeShare","type":"uint256"},{"name":"pricePerSegment","type":"uint256"},{"name":"pendingRewardCut","type":"uint256"},{"name":"pendingFeeShare","type":"uint256"},{"name":"pendingPricePerSegment","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unbond","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_numTranscoders","type":"uint256"}],"name":"setNumTranscoders","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"numActiveTranscoders","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_numActiveTranscoders","type":"uint256"}],"name":"setNumActiveTranscoders","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"}],"name":"isRegisteredTranscoder","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"unbondingPeriod","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxEarningsClaimsRounds","type":"uint256"}],"name":"setMaxEarningsClaimsRounds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_round","type":"uint256"}],"name":"getTotalActiveStake","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"},{"name":"_round","type":"uint256"}],"name":"isActiveTranscoder","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_rewardCut","type":"uint256"},{"name":"_feeShare","type":"uint256"},{"name":"_pricePerSegment","type":"uint256"}],"name":"transcoder","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getFirstTranscoderInPool","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"}],"name":"transcoderStatus","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_maxPricePerSegment","type":"uint256"},{"name":"_blockHash","type":"bytes32"},{"name":"_round","type":"uint256"}],"name":"electActiveTranscoder","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_controller","type":"address"}],"name":"setController","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_delegator","type":"address"},{"name":"_endRound","type":"uint256"}],"name":"pendingStake","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"}],"name":"transcoderTotalStake","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_delegator","type":"address"}],"name":"getDelegator","outputs":[{"name":"bondedAmount","type":"uint256"},{"name":"fees","type":"uint256"},{"name":"delegateAddress","type":"address"},{"name":"delegatedAmount","type":"uint256"},{"name":"startRound","type":"uint256"},{"name":"withdrawRound","type":"uint256"},{"name":"lastClaimRound","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"},{"name":"_to","type":"address"}],"name":"bond","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdrawStake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_unbondingPeriod","type":"uint64"}],"name":"setUnbondingPeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_transcoder","type":"address"},{"name":"_round","type":"uint256"}],"name":"activeTranscoderTotalStake","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_delegator","type":"address"},{"name":"_endRound","type":"uint256"}],"name":"pendingFees","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"controller","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_controller","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"transcoder","type":"address"},{"indexed":false,"name":"pendingRewardCut","type":"uint256"},{"indexed":false,"name":"pendingFeeShare","type":"uint256"},{"indexed":false,"name":"pendingPricePerSegment","type":"uint256"},{"indexed":false,"name":"registered","type":"bool"}],"name":"TranscoderUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"transcoder","type":"address"}],"name":"TranscoderEvicted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"transcoder","type":"address"}],"name":"TranscoderResigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"transcoder","type":"address"},{"indexed":false,"name":"finder","type":"address"},{"indexed":false,"name":"penalty","type":"uint256"},{"indexed":false,"name":"finderReward","type":"uint256"}],"name":"TranscoderSlashed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"transcoder","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Reward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"delegate","type":"address"},{"indexed":true,"name":"delegator","type":"address"}],"name":"Bond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"delegate","type":"address"},{"indexed":true,"name":"delegator","type":"address"}],"name":"Unbond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"delegator","type":"address"}],"name":"WithdrawStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"delegator","type":"address"}],"name":"WithdrawFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"controller","type":"address"}],"name":"SetController","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"param","type":"string"}],"name":"ParameterUpdate","type":"event"}]
Contract Creation Code
6060604052341561000f57600080fd5b6040516020806148308339810160405280805160008054600160a060020a03909216600160a060020a031990921691909117905550506147dc806100546000396000f3006060604052600436106101c95763ffffffff60e060020a600035041663038424c381146101ce5780631544fc67146101f3578063228cb7331461023657806322bf9d7c1461024b578063235c960314610276578063242ed69f146102b157806324454fc4146102c457806324b1babf146103115780632a4e0d55146103275780633aeb512c1461033a5780633da1c2f51461035f578063476343ee1461037557806351720b41146103885780635a2a75a91461039b5780635c50c356146103ae5780635dce9948146103c15780635df6a6bc1461041e57806360c79d001461043157806361e25d2314610447578063673a456b1461045a57806368ba170c146104705780636cf6d675146104a357806372d9f13d146104d357806377517765146104e95780637c0207cb146104ff57806385aaff621461052157806388a6c7491461053d5780638b2f16521461055057806391fdf6b11461057f57806392eefe9b1461059b5780639d0b2c7a146105ba5780639ef9df94146105dc578063a64ad595146105fb578063b78d27dc1461066c578063bed9d8611461068e578063f10d1de1146106a1578063f2083220146106c1578063f595f1cc146106e3578063f77c479114610705575b600080fd5b34156101d957600080fd5b6101e1610718565b60405190815260200160405180910390f35b34156101fe57600080fd5b610212600160a060020a036004351661071e565b6040518082600381111561022257fe5b60ff16815260200191505060405180910390f35b341561024157600080fd5b6102496108de565b005b341561025657600080fd5b610249600160a060020a0360043581169060243516604435606435610b7d565b341561028157600080fd5b610295600160a060020a0360043516611050565b604051600160a060020a03909116815260200160405180910390f35b34156102bc57600080fd5b6102496110db565b34156102cf57600080fd5b6102e6600160a060020a0360043516602435611644565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b341561031c57600080fd5b610249600435611685565b341561033257600080fd5b6101e161180f565b341561034557600080fd5b610249600160a060020a0360043516602435604435611889565b341561036a57600080fd5b6101e1600435611a1e565b341561038057600080fd5b610249611a33565b341561039357600080fd5b6101e1611c73565b34156103a657600080fd5b6101e1611c79565b34156103b957600080fd5b6101e1611cd3565b34156103cc57600080fd5b6103e0600160a060020a0360043516611cd9565b60405196875260208701959095526040808701949094526060860192909252608085015260a084015260c083019190915260e0909101905180910390f35b341561042957600080fd5b610249611d22565b341561043c57600080fd5b610249600435612133565b341561045257600080fd5b6101e1612285565b341561046557600080fd5b61024960043561228b565b341561047b57600080fd5b61048f600160a060020a03600435166123e9565b604051901515815260200160405180910390f35b34156104ae57600080fd5b6104b6612408565b60405167ffffffffffffffff909116815260200160405180910390f35b34156104de57600080fd5b610249600435612418565b34156104f457600080fd5b6101e16004356124f6565b341561050a57600080fd5b61048f600160a060020a036004351660243561250b565b341561052c57600080fd5b610249600435602435604435612539565b341561054857600080fd5b610295612e2f565b341561055b57600080fd5b61056f600160a060020a0360043516612e89565b6040518082600181111561022257fe5b341561058a57600080fd5b610295600435602435604435612f22565b34156105a657600080fd5b610249600160a060020a03600435166130f3565b34156105c557600080fd5b6101e1600160a060020a0360043516602435613176565b34156105e757600080fd5b6101e1600160a060020a03600435166132b6565b341561060657600080fd5b61061a600160a060020a036004351661331f565b6040518088815260200187815260200186600160a060020a0316600160a060020a0316815260200185815260200184815260200183815260200182815260200197505050505050505060405180910390f35b341561067757600080fd5b610249600435600160a060020a036024351661336c565b341561069957600080fd5b610249613a03565b34156106ac57600080fd5b61024967ffffffffffffffff60043516613bd1565b34156106cc57600080fd5b6101e1600160a060020a0360043516602435613cc7565b34156106ee57600080fd5b6101e1600160a060020a0360043516602435613d2b565b341561071057600080fd5b610295613e97565b60045481565b600160a060020a0381166000908152600560208190526040822090810154829011156107ca578060050154610751613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561079657600080fd5b6102c65a03f115156107a757600080fd5b505050604051805190501015156107c157600391506108d8565b600291506108d8565b6107d2613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561081757600080fd5b6102c65a03f1151561082857600080fd5b505050604051805190508160040154111561084657600091506108d8565b600081600401541180156108c5575061085d613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156108a257600080fd5b6102c65a03f115156108b357600080fd5b50505060405180519050816004015411155b156108d357600191506108d8565b600391505b50919050565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561092857600080fd5b6102c65a03f1151561093957600080fd5b505050604051805115905061094d57600080fd5b610955613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561099a57600080fd5b6102c65a03f115156109ab57600080fd5b5050506040518051905015156109c057600080fd5b6109c8613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610a0d57600080fd5b6102c65a03f11515610a1e57600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a033316845260010190915290205490935060ff1615159050610a5f57600080fd5b600160a060020a033316600090815260066020526040902054821415610a8457600080fd5b600160a060020a0333166000908152600660205260409020829055610aa7613f39565b600160a060020a0316637dbedad5610abf3385613cc7565b6000858152600d6020526040808220600201549190516020015260405160e060020a63ffffffff851602815260048101929092526024820152604401602060405180830381600087803b1515610b1457600080fd5b6102c65a03f11515610b2557600080fd5b505050604051805190509050610b3c338284613fbb565b33600160a060020a03167f619caafabdd75649b302ba8419e48cccf64f37f1983ac4727cfb38b57703ffc98260405190815260200160405180910390a25050565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610bcb57600080fd5b6102c65a03f11515610bdc57600080fd5b5050506040518051159050610bf057600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610c7157600080fd5b6102c65a03f11515610c8257600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515610cab57600080fd5b600160a060020a038816600090815260056020526040812080549095501115610fe157600160a060020a038816600090815260056020526040902054610cf19087614137565b8454909350610d06908463ffffffff61416316565b84556001610d138961071e565b6003811115610d1e57fe5b1415610d8b576002840154600160a060020a0316600090815260056020526040902060030154610d54908463ffffffff61416316565b6002850154600160a060020a0316600090815260056020526040902060030155600754610d87908463ffffffff61416316565b6007555b6001610d9689612e89565b6001811115610da157fe5b1415610db057610db088614175565b829150600160a060020a03871615610f1557610dcc8386614137565b9050610dd6613f39565b600160a060020a031663e7a49c2b888360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515610e2957600080fd5b6102c65a03f11515610e3a57600080fd5b505050610e45613f39565b600160a060020a031663c7ee98c2610e63848463ffffffff61416316565b60405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610e9957600080fd5b6102c65a03f11515610eaa57600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c228885846040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a2610fdc565b610f1d613f39565b600160a060020a031663c7ee98c28360405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610f6257600080fd5b6102c65a03f11515610f7357600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c2260008560006040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b611046565b87600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c22886000806040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b5050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156110b957600080fd5b6102c65a03f415156110ca57600080fd5b50505060405180519150505b919050565b6000806000806000806000806000806000809054906101000a9004600160a060020a0316600160a060020a0316635c975abb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561114457600080fd5b6102c65a03f1151561115557600080fd5b505050604051805115905061116957600080fd5b600054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156111ea57600080fd5b6102c65a03f115156111fb57600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561122457600080fd5b61122c613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561127157600080fd5b6102c65a03f1151561128257600080fd5b5050506040518051600354909b5061130e9150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156112ee57600080fd5b6102c65a03f415156112ff57600080fd5b5050506040518051905061431e565b985060009750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed60088a6040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561136c57600080fd5b6102c65a03f4151561137d57600080fd5b5050506040518051975060009650505b888610156116245760008a8152600d602052604090208054600181016113b38382614737565b506000918252602080832091909101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038b169081179091558c8352600d825260408084209184526001918201909252818320805460ff19169091179055731a0b2ca69ca2c7f96e2529faa6d63f881655d81a9163d8681128916008918b91516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561147857600080fd5b6102c65a03f4151561148957600080fd5b5050506040518051905094506006600088600160a060020a0316600160a060020a031681526020019081526020016000206004015493506006600088600160a060020a0316600160a060020a031681526020019081526020016000206005015492506006600088600160a060020a0316600160a060020a031681526020019081526020016000206006015491506006600088600160a060020a0316600160a060020a0316815260200190815260200160002090508381600101819055508281600201819055508181600301819055506115838585858460070160008f8152602001908152602001600020614334909392919063ffffffff16565b611593888663ffffffff61435016565b9750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088960006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156115fd57600080fd5b6102c65a03f4151561160e57600080fd5b505050604051805197505060019095019461138d565b50505060009687525050600d602052505060409092206002019190915550565b600160a060020a0390911660009081526006602090815260408083209383526007909301905220805460018201546002830154600390930154919390929190565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156116ce57600080fd5b6102c65a03f115156116df57600080fd5b50505060405180511590506116f357600080fd5b6116fb613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561174057600080fd5b6102c65a03f1151561175157600080fd5b50505060405180519050151561176657600080fd5b600160a060020a03331660009081526005602052604090206006015481901061178e57600080fd5b611796613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156117db57600080fd5b6102c65a03f115156117ec57600080fd5b5050506040518051821115905061180257600080fd5b61180c338261436a565b50565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece586008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561186957600080fd5b6102c65a03f4151561187a57600080fd5b50505060405180519150505b90565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156118d357600080fd5b6102c65a03f115156118e457600080fd5b50505060405180511590506118f857600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561197957600080fd5b6102c65a03f1151561198a57600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156119b357600080fd5b60016119be86612e89565b60018111156119c957fe5b146119d357600080fd5b5050600160a060020a0383166000908152600660209081526040808320848452600781019092529091206001810154611a12908563ffffffff61435016565b60019091015550505050565b600d6020526000908152604090206002015481565b60008054600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611a7b57600080fd5b6102c65a03f11515611a8c57600080fd5b5050506040518051159050611aa057600080fd5b611aa8613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611aed57600080fd5b6102c65a03f11515611afe57600080fd5b505050604051805190501515611b1357600080fd5b611b8433611b1f613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611b6457600080fd5b6102c65a03f11515611b7557600080fd5b5050506040518051905061436a565b600160a060020a03331660009081526005602052604081206001015411611baa57600080fd5b50600160a060020a03331660009081526005602052604081206001018054919055611bd3613f39565b600160a060020a03166320283da9338360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515611c2657600080fd5b6102c65a03f11515611c3757600080fd5b50505033600160a060020a03167fd3719f04262b628e1d01a6ed24707f542cda51f144b5271149c7d0419436d00c60405160405180910390a250565b60015481565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561186957600080fd5b60075490565b600160a060020a03166000908152600660208190526040909120805460018201546002830154600384015460048501546005860154959096015493969295919490939192909190565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611d6c57600080fd5b6102c65a03f11515611d7d57600080fd5b5050506040518051159050611d9157600080fd5b611d99613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611dde57600080fd5b6102c65a03f11515611def57600080fd5b505050604051805190501515611e0457600080fd5b611e1033611b1f613ea6565b6001611e1b3361071e565b6003811115611e2657fe5b14611e3057600080fd5b600160a060020a03331660009081526005602052604090209150611e52613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611e9757600080fd5b6102c65a03f11515611ea857600080fd5b5050506040518051600254909250611ed29150829067ffffffffffffffff1663ffffffff61435016565b60058084019190915582546002840154600160a060020a03166000908152602092909252604090912060030154611f0e9163ffffffff61416316565b6002830154600160a060020a03166000908152600560205260409020600301558154600754611f429163ffffffff61416316565b6007556001611f5033612e89565b6001811115611f5b57fe5b1415611f6a57611f6a33614175565b600282015433600160a060020a03908116911614801590611fac575060016002830154611f9f90600160a060020a0316612e89565b6001811115611faa57fe5b145b156120d05760028201548254731a0b2ca69ca2c7f96e2529faa6d63f881655d81a916338237efe91600891600160a060020a03169061205f908563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561203857600080fd5b6102c65a03f4151561204957600080fd5b505050604051805191905063ffffffff61416316565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156120bb57600080fd5b6102c65a03f415156120cc57600080fd5b5050505b60028201805473ffffffffffffffffffffffffffffffffffffffff1916905560006004830181905533600160a060020a0316907f4907de7e87b3873cb501376a57df5a00ff20db617b18f56eb5768717564a00e460405160405180910390a35050565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561217c57600080fd5b6102c65a03f1151561218d57600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156121b657600080fd5b6003548110156121c557600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63a176adaf60088360405160e060020a63ffffffff85160281526004810192909252602482015260440160006040518083038186803b151561221b57600080fd5b6102c65a03f4151561222c57600080fd5b5050506000805160206147918339815191526040516020808252600e908201527f6e756d5472616e73636f646572730000000000000000000000000000000000006040808301919091526060909101905180910390a150565b60035481565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156122d457600080fd5b6102c65a03f115156122e557600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561230e57600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561236757600080fd5b6102c65a03f4151561237857600080fd5b5050506040518051821115905061238e57600080fd5b600381905560008051602061479183398151915260405160208082526014908201527f6e756d4163746976655472616e73636f646572730000000000000000000000006040808301919091526060909101905180910390a150565b600060016123f683612e89565b600181111561240157fe5b1492915050565b60025467ffffffffffffffff1681565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561246157600080fd5b6102c65a03f1151561247257600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561249b57600080fd5b600481905560008051602061479183398151915260405160208082526017908201527f6d61784561726e696e6773436c61696d73526f756e64730000000000000000006040808301919091526060909101905180910390a150565b6000908152600d602052604090206002015490565b6000908152600d60209081526040808320600160a060020a0394909416835260019093019052205460ff1690565b60008054819081908190819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561258d57600080fd5b6102c65a03f1151561259e57600080fd5b50505060405180511590506125b257600080fd5b6125ba613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156125ff57600080fd5b6102c65a03f1151561261057600080fd5b50505060405180519050151561262557600080fd5b600160a060020a033316600090815260066020908152604080832060059092529091209097509550612655613ea6565b600160a060020a0316636841f2536000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561269a57600080fd5b6102c65a03f115156126ab57600080fd5b50505060405180519050156129715760016126c533612e89565b60018111156126d057fe5b146126da57600080fd5b60048701548a146126ea57600080fd5b600587015489146126fa57600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561275357600080fd5b6102c65a03f4151561276457600080fd5b5050506040518051600160a060020a0381166000908152600660208190526040822001549197509095509350505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156127eb57600080fd5b6102c65a03f415156127fc57600080fd5b505050604051805190508310156128e157600160a060020a038516600090815260066020819052604090912001548490101561285257600160a060020a0385166000908152600660208190526040909120015493505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088760006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156128ba57600080fd5b6102c65a03f415156128cb57600080fd5b5050506040518051955050600190920191612792565b8388101580156128f5575086600601548811155b151561290057600080fd5b87876006018190555033600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be7886004015489600501548b6001604051938452602084019290925260408084019190915290151560608301526080909101905180910390a2612e23565b61297a8a614490565b151561298557600080fd5b61298e89614490565b151561299957600080fd5b600286015433600160a060020a0390811691161480156129bb57508554600090115b15156129c657600080fd5b600487018a905560058701899055600687018890556003860154915060006129ed33612e89565b60018111156129f857fe5b1415612d4457731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634aa12990600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612a5757600080fd5b6102c65a03f41515612a6857600080fd5b505050604051805190501515612b0b57731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a66008338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515612af257600080fd5b6102c65a03f41515612b0357600080fd5b505050612d44565b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6372e40b26600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612b6457600080fd5b6102c65a03f41515612b7557600080fd5b50505060405180519150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a905063d868112860088360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612be957600080fd5b6102c65a03f41515612bfa57600080fd5b50505060405180519050821115612d4457731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088360405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b1515612c6a57600080fd5b6102c65a03f41515612c7b57600080fd5b5050506008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a69091338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515612cfa57600080fd5b6102c65a03f41515612d0b57600080fd5b50505080600160a060020a03167e05588101bf85a737dacb8be2233b33113aaa5c5743525cfbfe2f6a77c2f6ff60405160405180910390a25b33600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be78b8b8b6008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c4790913360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612ddc57600080fd5b6102c65a03f41515612ded57600080fd5b50505060405180519050604051938452602084019290925260408084019190915290151560608301526080909101905180910390a25b50505050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561186957600080fd5b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c47600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612ef257600080fd5b6102c65a03f41515612f0357600080fd5b5050506040518051905015612f1a575060016110d6565b5060006110d6565b600080612f2d614760565b6000848152600d6020526040808220549350819081908190819081908190899051805910612f585750595b908082528060200260200182016040525097506000965060009550600094505b888510156130535760008b8152600d60205260409020805486908110612f9a57fe5b60009182526020808320909101548d8352600d82526040808420600160a060020a0390921680855260019290920190925291205490945060ff168015612ffc5750600160a060020a0384166000908152600660205260409020600301548d9011155b15613048578388888151811061300e57fe5b600160a060020a03909216602092830290910190910152600190960195613045613038858d613cc7565b879063ffffffff61435016565b95505b600190940193612f78565b86151561306357600099506130e3565b858c81151561306e57fe5b06925060009150600090505b82821115801561308957508681105b156130c7576130bd6130b08983815181106130a057fe5b906020019060200201518d613cc7565b839063ffffffff61435016565b915060010161307a565b8760018203815181106130d657fe5b9060200190602002015199505b5050505050505050509392505050565b60005433600160a060020a0390811691161461310e57600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f7081604051600160a060020a03909116815260200160405180910390a150565b6000806000806000806000613189613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156131ce57600080fd5b6102c65a03f115156131df57600080fd5b5050506040518051600160a060020a038b1660009081526005602052604090209097509550508588118015906132185750846006015488115b151561322357600080fd5b8454600686015490945060010192505b8783116132a95750506002830154600160a060020a0390811660008181526006602090815260408083208684526007019091529020918916146132758261449a565b1561329e5761329b61328e83868463ffffffff6144a516565b859063ffffffff61435016565b93505b600190920191613233565b5091979650505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d8681128600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156110b957600080fd5b600160a060020a0390811660009081526005602081905260409091208054600182015460028301546003840154600485015495850154600690950154939792969190911694909390929091565b6000805481908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156133b857600080fd5b6102c65a03f115156133c957600080fd5b50505060405180511590506133dd57600080fd5b6133e5613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561342a57600080fd5b6102c65a03f1151561343b57600080fd5b50505060405180519050151561345057600080fd5b61345c33611b1f613ea6565b600160a060020a0333166000908152600560205260409020925061347e613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156134c357600080fd5b6102c65a03f115156134d457600080fd5b50505060405180519250859150600390506134ee3361071e565b60038111156134f957fe5b14806135185750600261350b3361071e565b600381111561351657fe5b145b156135545761352e82600163ffffffff61435016565b600484015560006005840155825461354d90829063ffffffff61435016565b9050613745565b6002830154600160a060020a03161580159061358057506002830154600160a060020a03858116911614155b1561374557600061359033612e89565b600181111561359b57fe5b146135a557600080fd5b6135b682600163ffffffff61435016565b600484015582546135ce90829063ffffffff61435016565b83546002850154600160a060020a0316600090815260056020526040902060030154919250613603919063ffffffff61416316565b6002840154600160a060020a03166000908152600560205260409020600301556001600284015461363c90600160a060020a0316612e89565b600181111561364757fe5b14156137455760028301548354731a0b2ca69ca2c7f96e2529faa6d63f881655d81a916338237efe91600891600160a060020a0316906136d4908563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561203857600080fd5b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561373057600080fd5b6102c65a03f4151561374157600080fd5b5050505b6000811161375257600080fd5b60028301805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03861690811790915560009081526005602052604090206003015461379b9082614350565b600160a060020a03851660009081526005602052604090206003015560016137c285612e89565b60018111156137cd57fe5b14156138f5576002830154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe906008908790613884908690869063d8681128908690600160a060020a031660006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561385d57600080fd5b6102c65a03f4151561386e57600080fd5b505050604051805191905063ffffffff61435016565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156138e057600080fd5b6102c65a03f415156138f157600080fd5b5050505b60008511156139bc578254613910908663ffffffff61435016565b8355600754613925908663ffffffff61435016565b60075561393061451c565b600160a060020a03166323b872dd33613947613f39565b8860006040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b15156139a057600080fd5b6102c65a03f115156139b157600080fd5b505050604051805150505b33600160a060020a031684600160a060020a03167f926f98e4b543897a75b3e34b7494ba68a47829d3aa39ffd9c478ccc51bfbfb4460405160405180910390a35050505050565b60008054600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613a4b57600080fd5b6102c65a03f11515613a5c57600080fd5b5050506040518051159050613a7057600080fd5b613a78613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613abd57600080fd5b6102c65a03f11515613ace57600080fd5b505050604051805190501515613ae357600080fd5b6003613aee3361071e565b6003811115613af957fe5b14613b0357600080fd5b50600160a060020a033316600090815260056020819052604082208054838255910191909155613b31613f39565b600160a060020a031663e7a49c2b338360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515613b8457600080fd5b6102c65a03f11515613b9557600080fd5b50505033600160a060020a03167f32b4834046d70a9d8d9c79995359892376424492753f04a190f871bbbc8d26ce60405160405180910390a250565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613c1a57600080fd5b6102c65a03f11515613c2b57600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515613c5457600080fd5b6002805467ffffffffffffffff191667ffffffffffffffff83161790556000805160206147918339815191526040516020808252600f908201527f756e626f6e64696e67506572696f6400000000000000000000000000000000006040808301919091526060909101905180910390a150565b6000818152600d60209081526040808320600160a060020a038616845260010190915281205460ff161515613cfb57600080fd5b50600160a060020a0391909116600090815260066020908152604080832093835260079093019052206002015490565b600080600080600080600080613d3f613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613d8457600080fd5b6102c65a03f11515613d9557600080fd5b5050506040518051600160a060020a038c166000908152600560205260409020909850965050868911801590613dce5750856006015489115b1515613dd957600080fd5b6001808701548754600689015491975095500192505b888311613e89576002860154600160a060020a0316600090815260066020908152604080832086845260070190915290209150613e2b8261449a565b15613e7e57506002850154600160a060020a038a8116911614613e65613e5883868463ffffffff61459e16565b869063ffffffff61435016565b9450613e7b61328e83868463ffffffff6144a516565b93505b600190920191613def565b509298975050505050505050565b600054600160a060020a031681565b60008054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515613f2857600080fd5b6102c65a03f1151561187a57600080fd5b60008054600160a060020a031663e16c7d986040517f4d696e74657200000000000000000000000000000000000000000000000000008152600601604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515613f2857600080fd5b600160a060020a03831660009081526006602090815260408083206005835281842085855260078201909352908320805491939091614000908763ffffffff61435016565b82556003830154614017908763ffffffff61435016565b600384015561408886731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d868112860088b60006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561385d57600080fd5b9050731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6338237efe6008898460008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561410457600080fd5b6102c65a03f4151561411557600080fd5b505060075461412b91508763ffffffff61435016565b60075550505050505050565b600061415c620f4240614150858563ffffffff61461d16565b9063ffffffff61464816565b9392505050565b60008282111561416f57fe5b50900390565b600061417f613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156141c457600080fd5b6102c65a03f115156141d557600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a038816845260010190915290205490925060ff161590506142715761423b61421d8383613cc7565b6000838152600d60205260409020600201549063ffffffff61416316565b6000828152600d602090815260408083206002810194909455600160a060020a03861683526001909301905220805460ff191690555b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088460405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b15156142d057600080fd5b6102c65a03f415156142e157600080fd5b50505081600160a060020a03167fc6be59bdc33151833b6dbb6823a9bddecde3c685a1bf4d253d20b4a93fbae56c60405160405180910390a25050565b600081831061432d578161415c565b5090919050565b6002840183905560038401929092556004830155600590910155565b60008282018381101561435f57fe5b8091505b5092915050565b600160a060020a03808316600090815260056020526040812060028101549092829182918291829182918291161561447d5760045460068901546143b5908b9063ffffffff61416316565b11156143c057600080fd5b87546001808a015460068b015492995097500194505b888511614472576002880154600160a060020a03166000908152600660209081526040808320888452600701909152902093506144128461449a565b15614467576002880154600160a060020a038b8116911614925061443d84888563ffffffff61465f16565b9092509050614452868363ffffffff61435016565b9550614464878263ffffffff61435016565b96505b6001909401936143d6565b868855600188018690555b5050505060069093019390935550505050565b620f424090111590565b600301546000901190565b600383015460009081908190819011156144f2576144cb86600001548760040154614137565b86549092506144ef906144e4908463ffffffff61416316565b8688600301546146f3565b90505b831561450f57614508818363ffffffff61435016565b9250614513565b8092505b50509392505050565b60008054600160a060020a031663e16c7d986040517f4c69766570656572546f6b656e000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515613f2857600080fd5b6003830154600090819081908190819011156145f2576145c687600101548860050154614137565b60018801549091506145de908263ffffffff61416316565b92506145ef818789600301546146f3565b91505b841561460f57614608828463ffffffff61435016565b9350614613565b8193505b5050509392505050565b6000808315156146305760009150614363565b5082820282848281151561464057fe5b041461435f57fe5b600080828481151561465657fe5b04949350505050565b60018301546000908190819081908190111561469e5761468087878761459e565b6001880154909250614698908363ffffffff61416316565b60018801555b865460009011156146cc576146b48787876144a5565b87549091506146c9908263ffffffff61416316565b87555b60038701546146e1908763ffffffff61416316565b60038801559092509050935093915050565b6000614716620f4240614150614709868661471e565b879063ffffffff61461d16565b949350505050565b600061415c8261415085620f424063ffffffff61461d16565b81548183558181151161475b5760008381526020902061475b918101908301614772565b505050565b60206040519081016040526000815290565b61188691905b8082111561478c5760008155600101614778565b509056009f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd674a165627a7a72305820dd0ce954ef7b6a6647e6719eeb9e945b0a8825cdeba54568e24951f4879770280029000000000000000000000000f96d54e490317c557a967abfa5d6e33006be69b3
Deployed Bytecode
0x6060604052600436106101c95763ffffffff60e060020a600035041663038424c381146101ce5780631544fc67146101f3578063228cb7331461023657806322bf9d7c1461024b578063235c960314610276578063242ed69f146102b157806324454fc4146102c457806324b1babf146103115780632a4e0d55146103275780633aeb512c1461033a5780633da1c2f51461035f578063476343ee1461037557806351720b41146103885780635a2a75a91461039b5780635c50c356146103ae5780635dce9948146103c15780635df6a6bc1461041e57806360c79d001461043157806361e25d2314610447578063673a456b1461045a57806368ba170c146104705780636cf6d675146104a357806372d9f13d146104d357806377517765146104e95780637c0207cb146104ff57806385aaff621461052157806388a6c7491461053d5780638b2f16521461055057806391fdf6b11461057f57806392eefe9b1461059b5780639d0b2c7a146105ba5780639ef9df94146105dc578063a64ad595146105fb578063b78d27dc1461066c578063bed9d8611461068e578063f10d1de1146106a1578063f2083220146106c1578063f595f1cc146106e3578063f77c479114610705575b600080fd5b34156101d957600080fd5b6101e1610718565b60405190815260200160405180910390f35b34156101fe57600080fd5b610212600160a060020a036004351661071e565b6040518082600381111561022257fe5b60ff16815260200191505060405180910390f35b341561024157600080fd5b6102496108de565b005b341561025657600080fd5b610249600160a060020a0360043581169060243516604435606435610b7d565b341561028157600080fd5b610295600160a060020a0360043516611050565b604051600160a060020a03909116815260200160405180910390f35b34156102bc57600080fd5b6102496110db565b34156102cf57600080fd5b6102e6600160a060020a0360043516602435611644565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b341561031c57600080fd5b610249600435611685565b341561033257600080fd5b6101e161180f565b341561034557600080fd5b610249600160a060020a0360043516602435604435611889565b341561036a57600080fd5b6101e1600435611a1e565b341561038057600080fd5b610249611a33565b341561039357600080fd5b6101e1611c73565b34156103a657600080fd5b6101e1611c79565b34156103b957600080fd5b6101e1611cd3565b34156103cc57600080fd5b6103e0600160a060020a0360043516611cd9565b60405196875260208701959095526040808701949094526060860192909252608085015260a084015260c083019190915260e0909101905180910390f35b341561042957600080fd5b610249611d22565b341561043c57600080fd5b610249600435612133565b341561045257600080fd5b6101e1612285565b341561046557600080fd5b61024960043561228b565b341561047b57600080fd5b61048f600160a060020a03600435166123e9565b604051901515815260200160405180910390f35b34156104ae57600080fd5b6104b6612408565b60405167ffffffffffffffff909116815260200160405180910390f35b34156104de57600080fd5b610249600435612418565b34156104f457600080fd5b6101e16004356124f6565b341561050a57600080fd5b61048f600160a060020a036004351660243561250b565b341561052c57600080fd5b610249600435602435604435612539565b341561054857600080fd5b610295612e2f565b341561055b57600080fd5b61056f600160a060020a0360043516612e89565b6040518082600181111561022257fe5b341561058a57600080fd5b610295600435602435604435612f22565b34156105a657600080fd5b610249600160a060020a03600435166130f3565b34156105c557600080fd5b6101e1600160a060020a0360043516602435613176565b34156105e757600080fd5b6101e1600160a060020a03600435166132b6565b341561060657600080fd5b61061a600160a060020a036004351661331f565b6040518088815260200187815260200186600160a060020a0316600160a060020a0316815260200185815260200184815260200183815260200182815260200197505050505050505060405180910390f35b341561067757600080fd5b610249600435600160a060020a036024351661336c565b341561069957600080fd5b610249613a03565b34156106ac57600080fd5b61024967ffffffffffffffff60043516613bd1565b34156106cc57600080fd5b6101e1600160a060020a0360043516602435613cc7565b34156106ee57600080fd5b6101e1600160a060020a0360043516602435613d2b565b341561071057600080fd5b610295613e97565b60045481565b600160a060020a0381166000908152600560208190526040822090810154829011156107ca578060050154610751613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561079657600080fd5b6102c65a03f115156107a757600080fd5b505050604051805190501015156107c157600391506108d8565b600291506108d8565b6107d2613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561081757600080fd5b6102c65a03f1151561082857600080fd5b505050604051805190508160040154111561084657600091506108d8565b600081600401541180156108c5575061085d613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156108a257600080fd5b6102c65a03f115156108b357600080fd5b50505060405180519050816004015411155b156108d357600191506108d8565b600391505b50919050565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561092857600080fd5b6102c65a03f1151561093957600080fd5b505050604051805115905061094d57600080fd5b610955613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561099a57600080fd5b6102c65a03f115156109ab57600080fd5b5050506040518051905015156109c057600080fd5b6109c8613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610a0d57600080fd5b6102c65a03f11515610a1e57600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a033316845260010190915290205490935060ff1615159050610a5f57600080fd5b600160a060020a033316600090815260066020526040902054821415610a8457600080fd5b600160a060020a0333166000908152600660205260409020829055610aa7613f39565b600160a060020a0316637dbedad5610abf3385613cc7565b6000858152600d6020526040808220600201549190516020015260405160e060020a63ffffffff851602815260048101929092526024820152604401602060405180830381600087803b1515610b1457600080fd5b6102c65a03f11515610b2557600080fd5b505050604051805190509050610b3c338284613fbb565b33600160a060020a03167f619caafabdd75649b302ba8419e48cccf64f37f1983ac4727cfb38b57703ffc98260405190815260200160405180910390a25050565b60008054819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610bcb57600080fd5b6102c65a03f11515610bdc57600080fd5b5050506040518051159050610bf057600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610c7157600080fd5b6102c65a03f11515610c8257600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515610cab57600080fd5b600160a060020a038816600090815260056020526040812080549095501115610fe157600160a060020a038816600090815260056020526040902054610cf19087614137565b8454909350610d06908463ffffffff61416316565b84556001610d138961071e565b6003811115610d1e57fe5b1415610d8b576002840154600160a060020a0316600090815260056020526040902060030154610d54908463ffffffff61416316565b6002850154600160a060020a0316600090815260056020526040902060030155600754610d87908463ffffffff61416316565b6007555b6001610d9689612e89565b6001811115610da157fe5b1415610db057610db088614175565b829150600160a060020a03871615610f1557610dcc8386614137565b9050610dd6613f39565b600160a060020a031663e7a49c2b888360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515610e2957600080fd5b6102c65a03f11515610e3a57600080fd5b505050610e45613f39565b600160a060020a031663c7ee98c2610e63848463ffffffff61416316565b60405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610e9957600080fd5b6102c65a03f11515610eaa57600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c228885846040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a2610fdc565b610f1d613f39565b600160a060020a031663c7ee98c28360405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610f6257600080fd5b6102c65a03f11515610f7357600080fd5b50505087600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c2260008560006040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b611046565b87600160a060020a03167ff4b71fed8e2c9a8c67c388bc6d35ad20b9368a24eed6d565459f2b277b6c0c22886000806040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a25b5050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156110b957600080fd5b6102c65a03f415156110ca57600080fd5b50505060405180519150505b919050565b6000806000806000806000806000806000809054906101000a9004600160a060020a0316600160a060020a0316635c975abb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561114457600080fd5b6102c65a03f1151561115557600080fd5b505050604051805115905061116957600080fd5b600054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156111ea57600080fd5b6102c65a03f115156111fb57600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561122457600080fd5b61122c613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561127157600080fd5b6102c65a03f1151561128257600080fd5b5050506040518051600354909b5061130e9150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156112ee57600080fd5b6102c65a03f415156112ff57600080fd5b5050506040518051905061431e565b985060009750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed60088a6040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561136c57600080fd5b6102c65a03f4151561137d57600080fd5b5050506040518051975060009650505b888610156116245760008a8152600d602052604090208054600181016113b38382614737565b506000918252602080832091909101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038b169081179091558c8352600d825260408084209184526001918201909252818320805460ff19169091179055731a0b2ca69ca2c7f96e2529faa6d63f881655d81a9163d8681128916008918b91516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561147857600080fd5b6102c65a03f4151561148957600080fd5b5050506040518051905094506006600088600160a060020a0316600160a060020a031681526020019081526020016000206004015493506006600088600160a060020a0316600160a060020a031681526020019081526020016000206005015492506006600088600160a060020a0316600160a060020a031681526020019081526020016000206006015491506006600088600160a060020a0316600160a060020a0316815260200190815260200160002090508381600101819055508281600201819055508181600301819055506115838585858460070160008f8152602001908152602001600020614334909392919063ffffffff16565b611593888663ffffffff61435016565b9750731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088960006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156115fd57600080fd5b6102c65a03f4151561160e57600080fd5b505050604051805197505060019095019461138d565b50505060009687525050600d602052505060409092206002019190915550565b600160a060020a0390911660009081526006602090815260408083209383526007909301905220805460018201546002830154600390930154919390929190565b60008054600160a060020a031690635c975abb90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156116ce57600080fd5b6102c65a03f115156116df57600080fd5b50505060405180511590506116f357600080fd5b6116fb613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561174057600080fd5b6102c65a03f1151561175157600080fd5b50505060405180519050151561176657600080fd5b600160a060020a03331660009081526005602052604090206006015481901061178e57600080fd5b611796613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156117db57600080fd5b6102c65a03f115156117ec57600080fd5b5050506040518051821115905061180257600080fd5b61180c338261436a565b50565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece586008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561186957600080fd5b6102c65a03f4151561187a57600080fd5b50505060405180519150505b90565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156118d357600080fd5b6102c65a03f115156118e457600080fd5b50505060405180511590506118f857600080fd5b600054600160a060020a031663e16c7d986040517f4a6f62734d616e616765720000000000000000000000000000000000000000008152600b01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561197957600080fd5b6102c65a03f1151561198a57600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156119b357600080fd5b60016119be86612e89565b60018111156119c957fe5b146119d357600080fd5b5050600160a060020a0383166000908152600660209081526040808320848452600781019092529091206001810154611a12908563ffffffff61435016565b60019091015550505050565b600d6020526000908152604090206002015481565b60008054600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611a7b57600080fd5b6102c65a03f11515611a8c57600080fd5b5050506040518051159050611aa057600080fd5b611aa8613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611aed57600080fd5b6102c65a03f11515611afe57600080fd5b505050604051805190501515611b1357600080fd5b611b8433611b1f613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611b6457600080fd5b6102c65a03f11515611b7557600080fd5b5050506040518051905061436a565b600160a060020a03331660009081526005602052604081206001015411611baa57600080fd5b50600160a060020a03331660009081526005602052604081206001018054919055611bd3613f39565b600160a060020a03166320283da9338360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515611c2657600080fd5b6102c65a03f11515611c3757600080fd5b50505033600160a060020a03167fd3719f04262b628e1d01a6ed24707f542cda51f144b5271149c7d0419436d00c60405160405180910390a250565b60015481565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561186957600080fd5b60075490565b600160a060020a03166000908152600660208190526040909120805460018201546002830154600384015460048501546005860154959096015493969295919490939192909190565b600080548190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611d6c57600080fd5b6102c65a03f11515611d7d57600080fd5b5050506040518051159050611d9157600080fd5b611d99613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611dde57600080fd5b6102c65a03f11515611def57600080fd5b505050604051805190501515611e0457600080fd5b611e1033611b1f613ea6565b6001611e1b3361071e565b6003811115611e2657fe5b14611e3057600080fd5b600160a060020a03331660009081526005602052604090209150611e52613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611e9757600080fd5b6102c65a03f11515611ea857600080fd5b5050506040518051600254909250611ed29150829067ffffffffffffffff1663ffffffff61435016565b60058084019190915582546002840154600160a060020a03166000908152602092909252604090912060030154611f0e9163ffffffff61416316565b6002830154600160a060020a03166000908152600560205260409020600301558154600754611f429163ffffffff61416316565b6007556001611f5033612e89565b6001811115611f5b57fe5b1415611f6a57611f6a33614175565b600282015433600160a060020a03908116911614801590611fac575060016002830154611f9f90600160a060020a0316612e89565b6001811115611faa57fe5b145b156120d05760028201548254731a0b2ca69ca2c7f96e2529faa6d63f881655d81a916338237efe91600891600160a060020a03169061205f908563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561203857600080fd5b6102c65a03f4151561204957600080fd5b505050604051805191905063ffffffff61416316565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156120bb57600080fd5b6102c65a03f415156120cc57600080fd5b5050505b60028201805473ffffffffffffffffffffffffffffffffffffffff1916905560006004830181905533600160a060020a0316907f4907de7e87b3873cb501376a57df5a00ff20db617b18f56eb5768717564a00e460405160405180910390a35050565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561217c57600080fd5b6102c65a03f1151561218d57600080fd5b50505060405180519050600160a060020a031633600160a060020a03161415156121b657600080fd5b6003548110156121c557600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63a176adaf60088360405160e060020a63ffffffff85160281526004810192909252602482015260440160006040518083038186803b151561221b57600080fd5b6102c65a03f4151561222c57600080fd5b5050506000805160206147918339815191526040516020808252600e908201527f6e756d5472616e73636f646572730000000000000000000000000000000000006040808301919091526060909101905180910390a150565b60035481565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156122d457600080fd5b6102c65a03f115156122e557600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561230e57600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63735bc2ca600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561236757600080fd5b6102c65a03f4151561237857600080fd5b5050506040518051821115905061238e57600080fd5b600381905560008051602061479183398151915260405160208082526014908201527f6e756d4163746976655472616e73636f646572730000000000000000000000006040808301919091526060909101905180910390a150565b600060016123f683612e89565b600181111561240157fe5b1492915050565b60025467ffffffffffffffff1681565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561246157600080fd5b6102c65a03f1151561247257600080fd5b50505060405180519050600160a060020a031633600160a060020a031614151561249b57600080fd5b600481905560008051602061479183398151915260405160208082526017908201527f6d61784561726e696e6773436c61696d73526f756e64730000000000000000006040808301919091526060909101905180910390a150565b6000908152600d602052604090206002015490565b6000908152600d60209081526040808320600160a060020a0394909416835260019093019052205460ff1690565b60008054819081908190819081908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561258d57600080fd5b6102c65a03f1151561259e57600080fd5b50505060405180511590506125b257600080fd5b6125ba613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156125ff57600080fd5b6102c65a03f1151561261057600080fd5b50505060405180519050151561262557600080fd5b600160a060020a033316600090815260066020908152604080832060059092529091209097509550612655613ea6565b600160a060020a0316636841f2536000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561269a57600080fd5b6102c65a03f115156126ab57600080fd5b50505060405180519050156129715760016126c533612e89565b60018111156126d057fe5b146126da57600080fd5b60048701548a146126ea57600080fd5b600587015489146126fa57600080fd5b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561275357600080fd5b6102c65a03f4151561276457600080fd5b5050506040518051600160a060020a0381166000908152600660208190526040822001549197509095509350505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b32ece58600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b15156127eb57600080fd5b6102c65a03f415156127fc57600080fd5b505050604051805190508310156128e157600160a060020a038516600090815260066020819052604090912001548490101561285257600160a060020a0385166000908152600660208190526040909120015493505b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63e189dedb60088760006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156128ba57600080fd5b6102c65a03f415156128cb57600080fd5b5050506040518051955050600190920191612792565b8388101580156128f5575086600601548811155b151561290057600080fd5b87876006018190555033600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be7886004015489600501548b6001604051938452602084019290925260408084019190915290151560608301526080909101905180910390a2612e23565b61297a8a614490565b151561298557600080fd5b61298e89614490565b151561299957600080fd5b600286015433600160a060020a0390811691161480156129bb57508554600090115b15156129c657600080fd5b600487018a905560058701899055600687018890556003860154915060006129ed33612e89565b60018111156129f857fe5b1415612d4457731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634aa12990600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612a5757600080fd5b6102c65a03f41515612a6857600080fd5b505050604051805190501515612b0b57731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a66008338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515612af257600080fd5b6102c65a03f41515612b0357600080fd5b505050612d44565b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6372e40b26600860006040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b1515612b6457600080fd5b6102c65a03f41515612b7557600080fd5b50505060405180519150731a0b2ca69ca2c7f96e2529faa6d63f881655d81a905063d868112860088360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612be957600080fd5b6102c65a03f41515612bfa57600080fd5b50505060405180519050821115612d4457731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088360405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b1515612c6a57600080fd5b6102c65a03f41515612c7b57600080fd5b5050506008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a634fbaa9a69091338560008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b1515612cfa57600080fd5b6102c65a03f41515612d0b57600080fd5b50505080600160a060020a03167e05588101bf85a737dacb8be2233b33113aaa5c5743525cfbfe2f6a77c2f6ff60405160405180910390a25b33600160a060020a03167fe01026d5db477d9ceaec44dc8efd731e76bcbc51256aecba7d28dd1cb4968be78b8b8b6008731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c4790913360006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612ddc57600080fd5b6102c65a03f41515612ded57600080fd5b50505060405180519050604051938452602084019290925260408084019190915290151560608301526080909101905180910390a25b50505050505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a632ebb2fed6008836040516020015260405160e060020a63ffffffff8416028152600481019190915260240160206040518083038186803b151561186957600080fd5b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63b0138c47600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b1515612ef257600080fd5b6102c65a03f41515612f0357600080fd5b5050506040518051905015612f1a575060016110d6565b5060006110d6565b600080612f2d614760565b6000848152600d6020526040808220549350819081908190819081908190899051805910612f585750595b908082528060200260200182016040525097506000965060009550600094505b888510156130535760008b8152600d60205260409020805486908110612f9a57fe5b60009182526020808320909101548d8352600d82526040808420600160a060020a0390921680855260019290920190925291205490945060ff168015612ffc5750600160a060020a0384166000908152600660205260409020600301548d9011155b15613048578388888151811061300e57fe5b600160a060020a03909216602092830290910190910152600190960195613045613038858d613cc7565b879063ffffffff61435016565b95505b600190940193612f78565b86151561306357600099506130e3565b858c81151561306e57fe5b06925060009150600090505b82821115801561308957508681105b156130c7576130bd6130b08983815181106130a057fe5b906020019060200201518d613cc7565b839063ffffffff61435016565b915060010161307a565b8760018203815181106130d657fe5b9060200190602002015199505b5050505050505050509392505050565b60005433600160a060020a0390811691161461310e57600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f7081604051600160a060020a03909116815260200160405180910390a150565b6000806000806000806000613189613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156131ce57600080fd5b6102c65a03f115156131df57600080fd5b5050506040518051600160a060020a038b1660009081526005602052604090209097509550508588118015906132185750846006015488115b151561322357600080fd5b8454600686015490945060010192505b8783116132a95750506002830154600160a060020a0390811660008181526006602090815260408083208684526007019091529020918916146132758261449a565b1561329e5761329b61328e83868463ffffffff6144a516565b859063ffffffff61435016565b93505b600190920191613233565b5091979650505050505050565b6000731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d8681128600884846040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b15156110b957600080fd5b600160a060020a0390811660009081526005602081905260409091208054600182015460028301546003840154600485015495850154600690950154939792969190911694909390929091565b6000805481908190600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156133b857600080fd5b6102c65a03f115156133c957600080fd5b50505060405180511590506133dd57600080fd5b6133e5613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561342a57600080fd5b6102c65a03f1151561343b57600080fd5b50505060405180519050151561345057600080fd5b61345c33611b1f613ea6565b600160a060020a0333166000908152600560205260409020925061347e613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156134c357600080fd5b6102c65a03f115156134d457600080fd5b50505060405180519250859150600390506134ee3361071e565b60038111156134f957fe5b14806135185750600261350b3361071e565b600381111561351657fe5b145b156135545761352e82600163ffffffff61435016565b600484015560006005840155825461354d90829063ffffffff61435016565b9050613745565b6002830154600160a060020a03161580159061358057506002830154600160a060020a03858116911614155b1561374557600061359033612e89565b600181111561359b57fe5b146135a557600080fd5b6135b682600163ffffffff61435016565b600484015582546135ce90829063ffffffff61435016565b83546002850154600160a060020a0316600090815260056020526040902060030154919250613603919063ffffffff61416316565b6002840154600160a060020a03166000908152600560205260409020600301556001600284015461363c90600160a060020a0316612e89565b600181111561364757fe5b14156137455760028301548354731a0b2ca69ca2c7f96e2529faa6d63f881655d81a916338237efe91600891600160a060020a0316906136d4908563d8681128858560006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561203857600080fd5b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561373057600080fd5b6102c65a03f4151561374157600080fd5b5050505b6000811161375257600080fd5b60028301805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03861690811790915560009081526005602052604090206003015461379b9082614350565b600160a060020a03851660009081526005602052604090206003015560016137c285612e89565b60018111156137cd57fe5b14156138f5576002830154731a0b2ca69ca2c7f96e2529faa6d63f881655d81a906338237efe906008908790613884908690869063d8681128908690600160a060020a031660006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561385d57600080fd5b6102c65a03f4151561386e57600080fd5b505050604051805191905063ffffffff61435016565b60008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b15156138e057600080fd5b6102c65a03f415156138f157600080fd5b5050505b60008511156139bc578254613910908663ffffffff61435016565b8355600754613925908663ffffffff61435016565b60075561393061451c565b600160a060020a03166323b872dd33613947613f39565b8860006040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b15156139a057600080fd5b6102c65a03f115156139b157600080fd5b505050604051805150505b33600160a060020a031684600160a060020a03167f926f98e4b543897a75b3e34b7494ba68a47829d3aa39ffd9c478ccc51bfbfb4460405160405180910390a35050505050565b60008054600160a060020a0316635c975abb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613a4b57600080fd5b6102c65a03f11515613a5c57600080fd5b5050506040518051159050613a7057600080fd5b613a78613ea6565b600160a060020a031663219bc76c6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613abd57600080fd5b6102c65a03f11515613ace57600080fd5b505050604051805190501515613ae357600080fd5b6003613aee3361071e565b6003811115613af957fe5b14613b0357600080fd5b50600160a060020a033316600090815260056020819052604082208054838255910191909155613b31613f39565b600160a060020a031663e7a49c2b338360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515613b8457600080fd5b6102c65a03f11515613b9557600080fd5b50505033600160a060020a03167f32b4834046d70a9d8d9c79995359892376424492753f04a190f871bbbc8d26ce60405160405180910390a250565b60008054600160a060020a031690638da5cb5b90604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613c1a57600080fd5b6102c65a03f11515613c2b57600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515613c5457600080fd5b6002805467ffffffffffffffff191667ffffffffffffffff83161790556000805160206147918339815191526040516020808252600f908201527f756e626f6e64696e67506572696f6400000000000000000000000000000000006040808301919091526060909101905180910390a150565b6000818152600d60209081526040808320600160a060020a038616845260010190915281205460ff161515613cfb57600080fd5b50600160a060020a0391909116600090815260066020908152604080832093835260079093019052206002015490565b600080600080600080600080613d3f613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613d8457600080fd5b6102c65a03f11515613d9557600080fd5b5050506040518051600160a060020a038c166000908152600560205260409020909850965050868911801590613dce5750856006015489115b1515613dd957600080fd5b6001808701548754600689015491975095500192505b888311613e89576002860154600160a060020a0316600090815260066020908152604080832086845260070190915290209150613e2b8261449a565b15613e7e57506002850154600160a060020a038a8116911614613e65613e5883868463ffffffff61459e16565b869063ffffffff61435016565b9450613e7b61328e83868463ffffffff6144a516565b93505b600190920191613def565b509298975050505050505050565b600054600160a060020a031681565b60008054600160a060020a031663e16c7d986040517f526f756e64734d616e61676572000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515613f2857600080fd5b6102c65a03f1151561187a57600080fd5b60008054600160a060020a031663e16c7d986040517f4d696e74657200000000000000000000000000000000000000000000000000008152600601604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515613f2857600080fd5b600160a060020a03831660009081526006602090815260408083206005835281842085855260078201909352908320805491939091614000908763ffffffff61435016565b82556003830154614017908763ffffffff61435016565b600384015561408886731a0b2ca69ca2c7f96e2529faa6d63f881655d81a63d868112860088b60006040516020015260405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160206040518083038186803b151561385d57600080fd5b9050731a0b2ca69ca2c7f96e2529faa6d63f881655d81a6338237efe6008898460008060405160e060020a63ffffffff88160281526004810195909552600160a060020a03938416602486015260448501929092528216606484015216608482015260a40160006040518083038186803b151561410457600080fd5b6102c65a03f4151561411557600080fd5b505060075461412b91508763ffffffff61435016565b60075550505050505050565b600061415c620f4240614150858563ffffffff61461d16565b9063ffffffff61464816565b9392505050565b60008282111561416f57fe5b50900390565b600061417f613ea6565b600160a060020a0316638a19c8bc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156141c457600080fd5b6102c65a03f115156141d557600080fd5b50505060405180516000818152600d60209081526040808320600160a060020a038816845260010190915290205490925060ff161590506142715761423b61421d8383613cc7565b6000838152600d60205260409020600201549063ffffffff61416316565b6000828152600d602090815260408083206002810194909455600160a060020a03861683526001909301905220805460ff191690555b731a0b2ca69ca2c7f96e2529faa6d63f881655d81a635d35e00760088460405160e060020a63ffffffff85160281526004810192909252600160a060020a0316602482015260440160006040518083038186803b15156142d057600080fd5b6102c65a03f415156142e157600080fd5b50505081600160a060020a03167fc6be59bdc33151833b6dbb6823a9bddecde3c685a1bf4d253d20b4a93fbae56c60405160405180910390a25050565b600081831061432d578161415c565b5090919050565b6002840183905560038401929092556004830155600590910155565b60008282018381101561435f57fe5b8091505b5092915050565b600160a060020a03808316600090815260056020526040812060028101549092829182918291829182918291161561447d5760045460068901546143b5908b9063ffffffff61416316565b11156143c057600080fd5b87546001808a015460068b015492995097500194505b888511614472576002880154600160a060020a03166000908152600660209081526040808320888452600701909152902093506144128461449a565b15614467576002880154600160a060020a038b8116911614925061443d84888563ffffffff61465f16565b9092509050614452868363ffffffff61435016565b9550614464878263ffffffff61435016565b96505b6001909401936143d6565b868855600188018690555b5050505060069093019390935550505050565b620f424090111590565b600301546000901190565b600383015460009081908190819011156144f2576144cb86600001548760040154614137565b86549092506144ef906144e4908463ffffffff61416316565b8688600301546146f3565b90505b831561450f57614508818363ffffffff61435016565b9250614513565b8092505b50509392505050565b60008054600160a060020a031663e16c7d986040517f4c69766570656572546f6b656e000000000000000000000000000000000000008152600d01604051809103902060006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515613f2857600080fd5b6003830154600090819081908190819011156145f2576145c687600101548860050154614137565b60018801549091506145de908263ffffffff61416316565b92506145ef818789600301546146f3565b91505b841561460f57614608828463ffffffff61435016565b9350614613565b8193505b5050509392505050565b6000808315156146305760009150614363565b5082820282848281151561464057fe5b041461435f57fe5b600080828481151561465657fe5b04949350505050565b60018301546000908190819081908190111561469e5761468087878761459e565b6001880154909250614698908363ffffffff61416316565b60018801555b865460009011156146cc576146b48787876144a5565b87549091506146c9908263ffffffff61416316565b87555b60038701546146e1908763ffffffff61416316565b60038801559092509050935093915050565b6000614716620f4240614150614709868661471e565b879063ffffffff61461d16565b949350505050565b600061415c8261415085620f424063ffffffff61461d16565b81548183558181151161475b5760008381526020902061475b918101908301614772565b505050565b60206040519081016040526000815290565b61188691905b8082111561478c5760008155600101614778565b509056009f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd674a165627a7a72305820dd0ce954ef7b6a6647e6719eeb9e945b0a8825cdeba54568e24951f4879770280029
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f96d54e490317c557a967abfa5d6e33006be69b3
-----Decoded View---------------
Arg [0] : _controller (address): 0xF96D54E490317c557A967ABfA5d6e33006BE69b3
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000f96d54e490317c557a967abfa5d6e33006be69b3
Swarm Source
bzzr://dd0ce954ef7b6a6647e6719eeb9e945b0a8825cdeba54568e24951f487977028
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.