Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View 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:
StakeManager
Compiler Version
v0.5.17+commit.d19bba13
Optimization Enabled:
Yes with 200 runs
Other Settings:
constantinople EvmVersion, GNU GPLv3 license
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-01-21 */ // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.2; /** * @title ERC20 interface * @dev see https://eips.ethereum.org/EIPS/eip-20 */ interface IERC20 { function transfer(address to, uint256 value) external returns (bool); function approve(address spender, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function totalSupply() external view returns (uint256); function balanceOf(address who) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } // File: openzeppelin-solidity/contracts/math/Math.sol pragma solidity ^0.5.2; /** * @title Math * @dev Assorted math operations */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Calculates the average of two numbers. Since these are integers, * averages of an even and odd number cannot be represented, and will be * rounded down. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } } // File: openzeppelin-solidity/contracts/math/SafeMath.sol pragma solidity ^0.5.2; /** * @title SafeMath * @dev Unsigned math operations with safety checks that revert on error */ library SafeMath { /** * @dev Multiplies two unsigned integers, reverts on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b); return c; } /** * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a); uint256 c = a - b; return c; } /** * @dev Adds two unsigned integers, reverts on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a); return c; } /** * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0); return a % b; } } // File: solidity-rlp/contracts/RLPReader.sol /* * @author Hamdi Allam [email protected] * Please reach out with any questions or concerns */ pragma solidity ^0.5.0; library RLPReader { uint8 constant STRING_SHORT_START = 0x80; uint8 constant STRING_LONG_START = 0xb8; uint8 constant LIST_SHORT_START = 0xc0; uint8 constant LIST_LONG_START = 0xf8; uint8 constant WORD_SIZE = 32; struct RLPItem { uint len; uint memPtr; } struct Iterator { RLPItem item; // Item that's being iterated over. uint nextPtr; // Position of the next item in the list. } /* * @dev Returns the next element in the iteration. Reverts if it has not next element. * @param self The iterator. * @return The next element in the iteration. */ function next(Iterator memory self) internal pure returns (RLPItem memory) { require(hasNext(self)); uint ptr = self.nextPtr; uint itemLength = _itemLength(ptr); self.nextPtr = ptr + itemLength; return RLPItem(itemLength, ptr); } /* * @dev Returns true if the iteration has more elements. * @param self The iterator. * @return true if the iteration has more elements. */ function hasNext(Iterator memory self) internal pure returns (bool) { RLPItem memory item = self.item; return self.nextPtr < item.memPtr + item.len; } /* * @param item RLP encoded bytes */ function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) { uint memPtr; assembly { memPtr := add(item, 0x20) } return RLPItem(item.length, memPtr); } /* * @dev Create an iterator. Reverts if item is not a list. * @param self The RLP item. * @return An 'Iterator' over the item. */ function iterator(RLPItem memory self) internal pure returns (Iterator memory) { require(isList(self)); uint ptr = self.memPtr + _payloadOffset(self.memPtr); return Iterator(self, ptr); } /* * @param item RLP encoded bytes */ function rlpLen(RLPItem memory item) internal pure returns (uint) { return item.len; } /* * @param item RLP encoded bytes */ function payloadLen(RLPItem memory item) internal pure returns (uint) { return item.len - _payloadOffset(item.memPtr); } /* * @param item RLP encoded list in bytes */ function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) { require(isList(item)); uint items = numItems(item); RLPItem[] memory result = new RLPItem[](items); uint memPtr = item.memPtr + _payloadOffset(item.memPtr); uint dataLen; for (uint i = 0; i < items; i++) { dataLen = _itemLength(memPtr); result[i] = RLPItem(dataLen, memPtr); memPtr = memPtr + dataLen; } return result; } // @return indicator whether encoded payload is a list. negate this function call for isData. function isList(RLPItem memory item) internal pure returns (bool) { if (item.len == 0) return false; uint8 byte0; uint memPtr = item.memPtr; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < LIST_SHORT_START) return false; return true; } /** RLPItem conversions into data types **/ // @returns raw rlp encoding in bytes function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) { bytes memory result = new bytes(item.len); if (result.length == 0) return result; uint ptr; assembly { ptr := add(0x20, result) } copy(item.memPtr, ptr, item.len); return result; } // any non-zero byte is considered true function toBoolean(RLPItem memory item) internal pure returns (bool) { require(item.len == 1); uint result; uint memPtr = item.memPtr; assembly { result := byte(0, mload(memPtr)) } return result == 0 ? false : true; } function toAddress(RLPItem memory item) internal pure returns (address) { // 1 byte for the length prefix require(item.len == 21); return address(toUint(item)); } function toUint(RLPItem memory item) internal pure returns (uint) { require(item.len > 0 && item.len <= 33); uint offset = _payloadOffset(item.memPtr); uint len = item.len - offset; uint result; uint memPtr = item.memPtr + offset; assembly { result := mload(memPtr) // shfit to the correct location if neccesary if lt(len, 32) { result := div(result, exp(256, sub(32, len))) } } return result; } // enforces 32 byte length function toUintStrict(RLPItem memory item) internal pure returns (uint) { // one byte prefix require(item.len == 33); uint result; uint memPtr = item.memPtr + 1; assembly { result := mload(memPtr) } return result; } function toBytes(RLPItem memory item) internal pure returns (bytes memory) { require(item.len > 0); uint offset = _payloadOffset(item.memPtr); uint len = item.len - offset; // data length bytes memory result = new bytes(len); uint destPtr; assembly { destPtr := add(0x20, result) } copy(item.memPtr + offset, destPtr, len); return result; } /* * Private Helpers */ // @return number of payload items inside an encoded list. function numItems(RLPItem memory item) private pure returns (uint) { if (item.len == 0) return 0; uint count = 0; uint currPtr = item.memPtr + _payloadOffset(item.memPtr); uint endPtr = item.memPtr + item.len; while (currPtr < endPtr) { currPtr = currPtr + _itemLength(currPtr); // skip over an item count++; } return count; } // @return entire rlp item byte length function _itemLength(uint memPtr) private pure returns (uint) { uint itemLen; uint byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) itemLen = 1; else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1; else if (byte0 < LIST_SHORT_START) { assembly { let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is memPtr := add(memPtr, 1) // skip over the first byte /* 32 byte word size */ let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len itemLen := add(dataLen, add(byteLen, 1)) } } else if (byte0 < LIST_LONG_START) { itemLen = byte0 - LIST_SHORT_START + 1; } else { assembly { let byteLen := sub(byte0, 0xf7) memPtr := add(memPtr, 1) let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length itemLen := add(dataLen, add(byteLen, 1)) } } return itemLen; } // @return number of bytes until the data function _payloadOffset(uint memPtr) private pure returns (uint) { uint byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) return 0; else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return 1; else if (byte0 < LIST_SHORT_START) // being explicit return byte0 - (STRING_LONG_START - 1) + 1; else return byte0 - (LIST_LONG_START - 1) + 1; } /* * @param src Pointer to source * @param dest Pointer to destination * @param len Amount of memory to copy from the source */ function copy(uint src, uint dest, uint len) private pure { if (len == 0) return; // copy as many word sizes as possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } src += WORD_SIZE; dest += WORD_SIZE; } // left over bytes. Mask is used to remove unwanted bytes from the word uint mask = 256 ** (WORD_SIZE - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) // zero out src let destpart := and(mload(dest), mask) // retrieve the bytes mstore(dest, or(destpart, srcpart)) } } } // File: contracts/common/lib/BytesLib.sol pragma solidity ^0.5.2; library BytesLib { function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore( 0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. ) ) } return tempBytes; } function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) { require(_bytes.length >= (_start + _length)); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add( add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)) ) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add( add( add(_bytes, lengthmod), mul(0x20, iszero(lengthmod)) ), _start ) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } // Pad a bytes array to 32 bytes function leftPad(bytes memory _bytes) internal pure returns (bytes memory) { // may underflow if bytes.length < 32. Hence using SafeMath.sub bytes memory newBytes = new bytes(SafeMath.sub(32, _bytes.length)); return concat(newBytes, _bytes); } function toBytes32(bytes memory b) internal pure returns (bytes32) { require(b.length >= 32, "Bytes array should atleast be 32 bytes"); bytes32 out; for (uint256 i = 0; i < 32; i++) { out |= bytes32(b[i] & 0xFF) >> (i * 8); } return out; } function toBytes4(bytes memory b) internal pure returns (bytes4 result) { assembly { result := mload(add(b, 32)) } } function fromBytes32(bytes32 x) internal pure returns (bytes memory) { bytes memory b = new bytes(32); for (uint256 i = 0; i < 32; i++) { b[i] = bytes1(uint8(uint256(x) / (2**(8 * (31 - i))))); } return b; } function fromUint(uint256 _num) internal pure returns (bytes memory _ret) { _ret = new bytes(32); assembly { mstore(add(_ret, 32), _num) } } function toUint(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= (_start + 32)); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= (_start + 20)); address tempAddress; assembly { tempAddress := div( mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000 ) } return tempAddress; } } // File: contracts/common/lib/ECVerify.sol pragma solidity ^0.5.2; library ECVerify { function ecrecovery(bytes32 hash, uint[3] memory sig) internal pure returns (address) { bytes32 r; bytes32 s; uint8 v; assembly { r := mload(sig) s := mload(add(sig, 32)) v := byte(31, mload(add(sig, 64))) } if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return address(0x0); } // https://github.com/ethereum/go-ethereum/issues/2053 if (v < 27) { v += 27; } if (v != 27 && v != 28) { return address(0x0); } // get address out of hash and signature address result = ecrecover(hash, v, r, s); // ecrecover returns zero on error require(result != address(0x0)); return result; } function ecrecovery(bytes32 hash, bytes memory sig) internal pure returns (address) { bytes32 r; bytes32 s; uint8 v; if (sig.length != 65) { return address(0x0); } assembly { r := mload(add(sig, 32)) s := mload(add(sig, 64)) v := and(mload(add(sig, 65)), 255) } // https://github.com/ethereum/go-ethereum/issues/2053 if (v < 27) { v += 27; } if (v != 27 && v != 28) { return address(0x0); } // get address out of hash and signature address result = ecrecover(hash, v, r, s); // ecrecover returns zero on error require(result != address(0x0)); return result; } function ecrecovery(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { // get address out of hash and signature address result = ecrecover(hash, v, r, s); // ecrecover returns zero on error require(result != address(0x0), "signature verification failed"); return result; } function ecverify(bytes32 hash, bytes memory sig, address signer) internal pure returns (bool) { return signer == ecrecovery(hash, sig); } } // File: contracts/common/lib/Merkle.sol pragma solidity ^0.5.2; library Merkle { function checkMembership( bytes32 leaf, uint256 index, bytes32 rootHash, bytes memory proof ) internal pure returns (bool) { require(proof.length % 32 == 0, "Invalid proof length"); uint256 proofHeight = proof.length / 32; // Proof of size n means, height of the tree is n+1. // In a tree of height n+1, max #leafs possible is 2 ^ n require(index < 2 ** proofHeight, "Leaf index is too big"); bytes32 proofElement; bytes32 computedHash = leaf; for (uint256 i = 32; i <= proof.length; i += 32) { assembly { proofElement := mload(add(proof, i)) } if (index % 2 == 0) { computedHash = keccak256( abi.encodePacked(computedHash, proofElement) ); } else { computedHash = keccak256( abi.encodePacked(proofElement, computedHash) ); } index = index / 2; } return computedHash == rootHash; } } // File: contracts/common/governance/IGovernance.sol pragma solidity ^0.5.2; interface IGovernance { function update(address target, bytes calldata data) external; } // File: contracts/common/governance/Governable.sol pragma solidity ^0.5.2; contract Governable { IGovernance public governance; constructor(address _governance) public { governance = IGovernance(_governance); } modifier onlyGovernance() { _assertGovernance(); _; } function _assertGovernance() private view { require( msg.sender == address(governance), "Only governance contract is authorized" ); } } // File: contracts/common/mixin/Lockable.sol pragma solidity ^0.5.2; contract Lockable { bool public locked; modifier onlyWhenUnlocked() { _assertUnlocked(); _; } function _assertUnlocked() private view { require(!locked, "locked"); } function lock() public { locked = true; } function unlock() public { locked = false; } } // File: contracts/common/mixin/GovernanceLockable.sol pragma solidity ^0.5.2; contract GovernanceLockable is Lockable, Governable { constructor(address governance) public Governable(governance) {} function lock() public onlyGovernance { super.lock(); } function unlock() public onlyGovernance { super.unlock(); } } // File: contracts/common/misc/DelegateProxyForwarder.sol pragma solidity ^0.5.2; contract DelegateProxyForwarder { function delegatedFwd(address _dst, bytes memory _calldata) internal { // solium-disable-next-line security/no-inline-assembly assembly { let result := delegatecall( sub(gas, 10000), _dst, add(_calldata, 0x20), mload(_calldata), 0, 0 ) let size := returndatasize let ptr := mload(0x40) returndatacopy(ptr, 0, size) // revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas. // if the call returned error data, forward it switch result case 0 { revert(ptr, size) } default { return(ptr, size) } } } function isContract(address _target) internal view returns (bool) { if (_target == address(0)) { return false; } uint256 size; assembly { size := extcodesize(_target) } return size > 0; } } // File: contracts/root/withdrawManager/IWithdrawManager.sol pragma solidity ^0.5.2; contract IWithdrawManager { function createExitQueue(address token) external; function verifyInclusion( bytes calldata data, uint8 offset, bool verifyTxInclusion ) external view returns (uint256 age); function addExitToQueue( address exitor, address childToken, address rootToken, uint256 exitAmountOrTokenId, bytes32 txHash, bool isRegularExit, uint256 priority ) external; function addInput( uint256 exitId, uint256 age, address utxoOwner, address token ) external; function challengeExit( uint256 exitId, uint256 inputId, bytes calldata challengeData, address adjudicatorPredicate ) external; } // File: contracts/common/Registry.sol pragma solidity ^0.5.2; contract Registry is Governable { // @todo hardcode constants bytes32 private constant WETH_TOKEN = keccak256("wethToken"); bytes32 private constant DEPOSIT_MANAGER = keccak256("depositManager"); bytes32 private constant STAKE_MANAGER = keccak256("stakeManager"); bytes32 private constant VALIDATOR_SHARE = keccak256("validatorShare"); bytes32 private constant WITHDRAW_MANAGER = keccak256("withdrawManager"); bytes32 private constant CHILD_CHAIN = keccak256("childChain"); bytes32 private constant STATE_SENDER = keccak256("stateSender"); bytes32 private constant SLASHING_MANAGER = keccak256("slashingManager"); address public erc20Predicate; address public erc721Predicate; mapping(bytes32 => address) public contractMap; mapping(address => address) public rootToChildToken; mapping(address => address) public childToRootToken; mapping(address => bool) public proofValidatorContracts; mapping(address => bool) public isERC721; enum Type {Invalid, ERC20, ERC721, Custom} struct Predicate { Type _type; } mapping(address => Predicate) public predicates; event TokenMapped(address indexed rootToken, address indexed childToken); event ProofValidatorAdded(address indexed validator, address indexed from); event ProofValidatorRemoved(address indexed validator, address indexed from); event PredicateAdded(address indexed predicate, address indexed from); event PredicateRemoved(address indexed predicate, address indexed from); event ContractMapUpdated(bytes32 indexed key, address indexed previousContract, address indexed newContract); constructor(address _governance) public Governable(_governance) {} function updateContractMap(bytes32 _key, address _address) external onlyGovernance { emit ContractMapUpdated(_key, contractMap[_key], _address); contractMap[_key] = _address; } /** * @dev Map root token to child token * @param _rootToken Token address on the root chain * @param _childToken Token address on the child chain * @param _isERC721 Is the token being mapped ERC721 */ function mapToken( address _rootToken, address _childToken, bool _isERC721 ) external onlyGovernance { require(_rootToken != address(0x0) && _childToken != address(0x0), "INVALID_TOKEN_ADDRESS"); rootToChildToken[_rootToken] = _childToken; childToRootToken[_childToken] = _rootToken; isERC721[_rootToken] = _isERC721; IWithdrawManager(contractMap[WITHDRAW_MANAGER]).createExitQueue(_rootToken); emit TokenMapped(_rootToken, _childToken); } function addErc20Predicate(address predicate) public onlyGovernance { require(predicate != address(0x0), "Can not add null address as predicate"); erc20Predicate = predicate; addPredicate(predicate, Type.ERC20); } function addErc721Predicate(address predicate) public onlyGovernance { erc721Predicate = predicate; addPredicate(predicate, Type.ERC721); } function addPredicate(address predicate, Type _type) public onlyGovernance { require(predicates[predicate]._type == Type.Invalid, "Predicate already added"); predicates[predicate]._type = _type; emit PredicateAdded(predicate, msg.sender); } function removePredicate(address predicate) public onlyGovernance { require(predicates[predicate]._type != Type.Invalid, "Predicate does not exist"); delete predicates[predicate]; emit PredicateRemoved(predicate, msg.sender); } function getValidatorShareAddress() public view returns (address) { return contractMap[VALIDATOR_SHARE]; } function getWethTokenAddress() public view returns (address) { return contractMap[WETH_TOKEN]; } function getDepositManagerAddress() public view returns (address) { return contractMap[DEPOSIT_MANAGER]; } function getStakeManagerAddress() public view returns (address) { return contractMap[STAKE_MANAGER]; } function getSlashingManagerAddress() public view returns (address) { return contractMap[SLASHING_MANAGER]; } function getWithdrawManagerAddress() public view returns (address) { return contractMap[WITHDRAW_MANAGER]; } function getChildChainAndStateSender() public view returns (address, address) { return (contractMap[CHILD_CHAIN], contractMap[STATE_SENDER]); } function isTokenMapped(address _token) public view returns (bool) { return rootToChildToken[_token] != address(0x0); } function isTokenMappedAndIsErc721(address _token) public view returns (bool) { require(isTokenMapped(_token), "TOKEN_NOT_MAPPED"); return isERC721[_token]; } function isTokenMappedAndGetPredicate(address _token) public view returns (address) { if (isTokenMappedAndIsErc721(_token)) { return erc721Predicate; } return erc20Predicate; } function isChildTokenErc721(address childToken) public view returns (bool) { address rootToken = childToRootToken[childToken]; require(rootToken != address(0x0), "Child token is not mapped"); return isERC721[rootToken]; } } // File: contracts/staking/stakeManager/IStakeManager.sol pragma solidity 0.5.17; contract IStakeManager { // validator replacement function startAuction( uint256 validatorId, uint256 amount, bool acceptDelegation, bytes calldata signerPubkey ) external; function confirmAuctionBid(uint256 validatorId, uint256 heimdallFee) external; function transferFunds( uint256 validatorId, uint256 amount, address delegator ) external returns (bool); function delegationDeposit( uint256 validatorId, uint256 amount, address delegator ) external returns (bool); function unstake(uint256 validatorId) external; function totalStakedFor(address addr) external view returns (uint256); function stakeFor( address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey ) public; function checkSignatures( uint256 blockInterval, bytes32 voteHash, bytes32 stateRoot, address proposer, uint[3][] calldata sigs ) external returns (uint256); function updateValidatorState(uint256 validatorId, int256 amount) public; function ownerOf(uint256 tokenId) public view returns (address); function slash(bytes calldata slashingInfoList) external returns (uint256); function validatorStake(uint256 validatorId) public view returns (uint256); function epoch() public view returns (uint256); function getRegistry() public view returns (address); function withdrawalDelay() public view returns (uint256); function delegatedAmount(uint256 validatorId) public view returns(uint256); function decreaseValidatorDelegatedAmount(uint256 validatorId, uint256 amount) public; function withdrawDelegatorsReward(uint256 validatorId) public returns(uint256); function delegatorsReward(uint256 validatorId) public view returns(uint256); function dethroneAndStake( address auctionUser, uint256 heimdallFee, uint256 validatorId, uint256 auctionAmount, bool acceptDelegation, bytes calldata signerPubkey ) external; } // File: contracts/staking/validatorShare/IValidatorShare.sol pragma solidity 0.5.17; // note this contract interface is only for stakeManager use contract IValidatorShare { function withdrawRewards() public; function unstakeClaimTokens() public; function getLiquidRewards(address user) public view returns (uint256); function owner() public view returns (address); function restake() public returns(uint256, uint256); function unlock() external; function lock() external; function drain( address token, address payable destination, uint256 amount ) external; function slash(uint256 valPow, uint256 delegatedAmount, uint256 totalAmountToSlash) external returns (uint256); function updateDelegation(bool delegation) external; function migrateOut(address user, uint256 amount) external; function migrateIn(address user, uint256 amount) external; } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol pragma solidity ^0.5.2; /** * @title Standard ERC20 token * * @dev Implementation of the basic standard token. * https://eips.ethereum.org/EIPS/eip-20 * Originally based on code by FirstBlood: * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol * * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for * all accounts just by listening to said events. Note that this isn't required by the specification, and other * compliant implementations may not do it. */ contract ERC20 is IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowed; uint256 private _totalSupply; /** * @dev Total number of tokens in existence */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev Gets the balance of the specified address. * @param owner The address to query the balance of. * @return A uint256 representing the amount owned by the passed address. */ function balanceOf(address owner) public view returns (uint256) { return _balances[owner]; } /** * @dev Function to check the amount of tokens that an owner allowed to a spender. * @param owner address The address which owns the funds. * @param spender address The address which will spend the funds. * @return A uint256 specifying the amount of tokens still available for the spender. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowed[owner][spender]; } /** * @dev Transfer token to a specified address * @param to The address to transfer to. * @param value The amount to be transferred. */ function transfer(address to, uint256 value) public returns (bool) { _transfer(msg.sender, to, value); return true; } /** * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. * Beware that changing an allowance with this method brings the risk that someone may use both the old * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. */ function approve(address spender, uint256 value) public returns (bool) { _approve(msg.sender, spender, value); return true; } /** * @dev Transfer tokens from one address to another. * Note that while this function emits an Approval event, this is not required as per the specification, * and other compliant implementations may not emit the event. * @param from address The address which you want to send tokens from * @param to address The address which you want to transfer to * @param value uint256 the amount of tokens to be transferred */ function transferFrom(address from, address to, uint256 value) public returns (bool) { _transfer(from, to, value); _approve(from, msg.sender, _allowed[from][msg.sender].sub(value)); return true; } /** * @dev Increase the amount of tokens that an owner allowed to a spender. * approve should be called when _allowed[msg.sender][spender] == 0. To increment * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * Emits an Approval event. * @param spender The address which will spend the funds. * @param addedValue The amount of tokens to increase the allowance by. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue)); return true; } /** * @dev Decrease the amount of tokens that an owner allowed to a spender. * approve should be called when _allowed[msg.sender][spender] == 0. To decrement * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * Emits an Approval event. * @param spender The address which will spend the funds. * @param subtractedValue The amount of tokens to decrease the allowance by. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue)); return true; } /** * @dev Transfer token for a specified addresses * @param from The address to transfer from. * @param to The address to transfer to. * @param value The amount to be transferred. */ function _transfer(address from, address to, uint256 value) internal { require(to != address(0)); _balances[from] = _balances[from].sub(value); _balances[to] = _balances[to].add(value); emit Transfer(from, to, value); } /** * @dev Internal function that mints an amount of the token and assigns it to * an account. This encapsulates the modification of balances such that the * proper events are emitted. * @param account The account that will receive the created tokens. * @param value The amount that will be created. */ function _mint(address account, uint256 value) internal { require(account != address(0)); _totalSupply = _totalSupply.add(value); _balances[account] = _balances[account].add(value); emit Transfer(address(0), account, value); } /** * @dev Internal function that burns an amount of the token of a given * account. * @param account The account whose tokens will be burnt. * @param value The amount that will be burnt. */ function _burn(address account, uint256 value) internal { require(account != address(0)); _totalSupply = _totalSupply.sub(value); _balances[account] = _balances[account].sub(value); emit Transfer(account, address(0), value); } /** * @dev Approve an address to spend another addresses' tokens. * @param owner The address that owns the tokens. * @param spender The address that will spend the tokens. * @param value The number of tokens that can be spent. */ function _approve(address owner, address spender, uint256 value) internal { require(spender != address(0)); require(owner != address(0)); _allowed[owner][spender] = value; emit Approval(owner, spender, value); } /** * @dev Internal function that burns an amount of the token of a given * account, deducting from the sender's allowance for said account. Uses the * internal burn function. * Emits an Approval event (reflecting the reduced allowance). * @param account The account whose tokens will be burnt. * @param value The amount that will be burnt. */ function _burnFrom(address account, uint256 value) internal { _burn(account, value); _approve(account, msg.sender, _allowed[account][msg.sender].sub(value)); } } // File: contracts/common/tokens/ERC20NonTradable.sol pragma solidity ^0.5.2; contract ERC20NonTradable is ERC20 { function _approve( address owner, address spender, uint256 value ) internal { revert("disabled"); } } // File: openzeppelin-solidity/contracts/ownership/Ownable.sol pragma solidity ^0.5.2; /** * @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 private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ constructor () internal { _owner = msg.sender; emit OwnershipTransferred(address(0), _owner); } /** * @return the address of the owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner()); _; } /** * @return true if `msg.sender` is the owner of the contract. */ function isOwner() public view returns (bool) { return msg.sender == _owner; } /** * @dev Allows the current owner to relinquish control of the contract. * It will not be possible to call the functions with the `onlyOwner` * modifier anymore. * @notice Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @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 { _transferOwnership(newOwner); } /** * @dev Transfers control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0)); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: contracts/staking/StakingInfo.sol pragma solidity ^0.5.2; // dummy interface to avoid cyclic dependency contract IStakeManagerLocal { enum Status {Inactive, Active, Locked, Unstaked} struct Validator { uint256 amount; uint256 reward; uint256 activationEpoch; uint256 deactivationEpoch; uint256 jailTime; address signer; address contractAddress; Status status; } mapping(uint256 => Validator) public validators; bytes32 public accountStateRoot; uint256 public activeAmount; // delegation amount from validator contract uint256 public validatorRewards; function currentValidatorSetTotalStake() public view returns (uint256); // signer to Validator mapping function signerToValidator(address validatorAddress) public view returns (uint256); function isValidator(uint256 validatorId) public view returns (bool); } contract StakingInfo is Ownable { using SafeMath for uint256; mapping(uint256 => uint256) public validatorNonce; /// @dev Emitted when validator stakes in '_stakeFor()' in StakeManager. /// @param signer validator address. /// @param validatorId unique integer to identify a validator. /// @param nonce to synchronize the events in heimdal. /// @param activationEpoch validator's first epoch as proposer. /// @param amount staking amount. /// @param total total staking amount. /// @param signerPubkey public key of the validator event Staked( address indexed signer, uint256 indexed validatorId, uint256 nonce, uint256 indexed activationEpoch, uint256 amount, uint256 total, bytes signerPubkey ); /// @dev Emitted when validator unstakes in 'unstakeClaim()' /// @param user address of the validator. /// @param validatorId unique integer to identify a validator. /// @param amount staking amount. /// @param total total staking amount. event Unstaked( address indexed user, uint256 indexed validatorId, uint256 amount, uint256 total ); /// @dev Emitted when validator unstakes in '_unstake()'. /// @param user address of the validator. /// @param validatorId unique integer to identify a validator. /// @param nonce to synchronize the events in heimdal. /// @param deactivationEpoch last epoch for validator. /// @param amount staking amount. event UnstakeInit( address indexed user, uint256 indexed validatorId, uint256 nonce, uint256 deactivationEpoch, uint256 indexed amount ); /// @dev Emitted when the validator public key is updated in 'updateSigner()'. /// @param validatorId unique integer to identify a validator. /// @param nonce to synchronize the events in heimdal. /// @param oldSigner old address of the validator. /// @param newSigner new address of the validator. /// @param signerPubkey public key of the validator. event SignerChange( uint256 indexed validatorId, uint256 nonce, address indexed oldSigner, address indexed newSigner, bytes signerPubkey ); event Restaked(uint256 indexed validatorId, uint256 amount, uint256 total); event Jailed( uint256 indexed validatorId, uint256 indexed exitEpoch, address indexed signer ); event UnJailed(uint256 indexed validatorId, address indexed signer); event Slashed(uint256 indexed nonce, uint256 indexed amount); event ThresholdChange(uint256 newThreshold, uint256 oldThreshold); event DynastyValueChange(uint256 newDynasty, uint256 oldDynasty); event ProposerBonusChange( uint256 newProposerBonus, uint256 oldProposerBonus ); event RewardUpdate(uint256 newReward, uint256 oldReward); /// @dev Emitted when validator confirms the auction bid and at the time of restaking in confirmAuctionBid() and restake(). /// @param validatorId unique integer to identify a validator. /// @param nonce to synchronize the events in heimdal. /// @param newAmount the updated stake amount. event StakeUpdate( uint256 indexed validatorId, uint256 indexed nonce, uint256 indexed newAmount ); event ClaimRewards( uint256 indexed validatorId, uint256 indexed amount, uint256 indexed totalAmount ); event StartAuction( uint256 indexed validatorId, uint256 indexed amount, uint256 indexed auctionAmount ); event ConfirmAuction( uint256 indexed newValidatorId, uint256 indexed oldValidatorId, uint256 indexed amount ); event TopUpFee(address indexed user, uint256 indexed fee); event ClaimFee(address indexed user, uint256 indexed fee); // Delegator events event ShareMinted( uint256 indexed validatorId, address indexed user, uint256 indexed amount, uint256 tokens ); event ShareBurned( uint256 indexed validatorId, address indexed user, uint256 indexed amount, uint256 tokens ); event DelegatorClaimedRewards( uint256 indexed validatorId, address indexed user, uint256 indexed rewards ); event DelegatorRestaked( uint256 indexed validatorId, address indexed user, uint256 indexed totalStaked ); event DelegatorUnstaked( uint256 indexed validatorId, address indexed user, uint256 amount ); event UpdateCommissionRate( uint256 indexed validatorId, uint256 indexed newCommissionRate, uint256 indexed oldCommissionRate ); Registry public registry; modifier onlyValidatorContract(uint256 validatorId) { address _contract; (, , , , , , _contract, ) = IStakeManagerLocal( registry.getStakeManagerAddress() ) .validators(validatorId); require(_contract == msg.sender, "Invalid sender, not validator"); _; } modifier StakeManagerOrValidatorContract(uint256 validatorId) { address _contract; address _stakeManager = registry.getStakeManagerAddress(); (, , , , , , _contract, ) = IStakeManagerLocal(_stakeManager).validators( validatorId ); require(_contract == msg.sender || _stakeManager == msg.sender, "Invalid sender, not stake manager or validator contract"); _; } modifier onlyStakeManager() { require(registry.getStakeManagerAddress() == msg.sender, "Invalid sender, not stake manager"); _; } modifier onlySlashingManager() { require(registry.getSlashingManagerAddress() == msg.sender, "Invalid sender, not slashing manager"); _; } constructor(address _registry) public { registry = Registry(_registry); } function updateNonce( uint256[] calldata validatorIds, uint256[] calldata nonces ) external onlyOwner { require(validatorIds.length == nonces.length, "args length mismatch"); for (uint256 i = 0; i < validatorIds.length; ++i) { validatorNonce[validatorIds[i]] = nonces[i]; } } function logStaked( address signer, bytes memory signerPubkey, uint256 validatorId, uint256 activationEpoch, uint256 amount, uint256 total ) public onlyStakeManager { validatorNonce[validatorId] = validatorNonce[validatorId].add(1); emit Staked( signer, validatorId, validatorNonce[validatorId], activationEpoch, amount, total, signerPubkey ); } function logUnstaked( address user, uint256 validatorId, uint256 amount, uint256 total ) public onlyStakeManager { emit Unstaked(user, validatorId, amount, total); } function logUnstakeInit( address user, uint256 validatorId, uint256 deactivationEpoch, uint256 amount ) public onlyStakeManager { validatorNonce[validatorId] = validatorNonce[validatorId].add(1); emit UnstakeInit( user, validatorId, validatorNonce[validatorId], deactivationEpoch, amount ); } function logSignerChange( uint256 validatorId, address oldSigner, address newSigner, bytes memory signerPubkey ) public onlyStakeManager { validatorNonce[validatorId] = validatorNonce[validatorId].add(1); emit SignerChange( validatorId, validatorNonce[validatorId], oldSigner, newSigner, signerPubkey ); } function logRestaked(uint256 validatorId, uint256 amount, uint256 total) public onlyStakeManager { emit Restaked(validatorId, amount, total); } function logJailed(uint256 validatorId, uint256 exitEpoch, address signer) public onlyStakeManager { emit Jailed(validatorId, exitEpoch, signer); } function logUnjailed(uint256 validatorId, address signer) public onlyStakeManager { emit UnJailed(validatorId, signer); } function logSlashed(uint256 nonce, uint256 amount) public onlySlashingManager { emit Slashed(nonce, amount); } function logThresholdChange(uint256 newThreshold, uint256 oldThreshold) public onlyStakeManager { emit ThresholdChange(newThreshold, oldThreshold); } function logDynastyValueChange(uint256 newDynasty, uint256 oldDynasty) public onlyStakeManager { emit DynastyValueChange(newDynasty, oldDynasty); } function logProposerBonusChange( uint256 newProposerBonus, uint256 oldProposerBonus ) public onlyStakeManager { emit ProposerBonusChange(newProposerBonus, oldProposerBonus); } function logRewardUpdate(uint256 newReward, uint256 oldReward) public onlyStakeManager { emit RewardUpdate(newReward, oldReward); } function logStakeUpdate(uint256 validatorId) public StakeManagerOrValidatorContract(validatorId) { validatorNonce[validatorId] = validatorNonce[validatorId].add(1); emit StakeUpdate( validatorId, validatorNonce[validatorId], totalValidatorStake(validatorId) ); } function logClaimRewards( uint256 validatorId, uint256 amount, uint256 totalAmount ) public onlyStakeManager { emit ClaimRewards(validatorId, amount, totalAmount); } function logStartAuction( uint256 validatorId, uint256 amount, uint256 auctionAmount ) public onlyStakeManager { emit StartAuction(validatorId, amount, auctionAmount); } function logConfirmAuction( uint256 newValidatorId, uint256 oldValidatorId, uint256 amount ) public onlyStakeManager { emit ConfirmAuction(newValidatorId, oldValidatorId, amount); } function logTopUpFee(address user, uint256 fee) public onlyStakeManager { emit TopUpFee(user, fee); } function logClaimFee(address user, uint256 fee) public onlyStakeManager { emit ClaimFee(user, fee); } function getStakerDetails(uint256 validatorId) public view returns ( uint256 amount, uint256 reward, uint256 activationEpoch, uint256 deactivationEpoch, address signer, uint256 _status ) { IStakeManagerLocal stakeManager = IStakeManagerLocal( registry.getStakeManagerAddress() ); address _contract; IStakeManagerLocal.Status status; ( amount, reward, activationEpoch, deactivationEpoch, , signer, _contract, status ) = stakeManager.validators(validatorId); _status = uint256(status); if (_contract != address(0x0)) { reward += IStakeManagerLocal(_contract).validatorRewards(); } } function totalValidatorStake(uint256 validatorId) public view returns (uint256 validatorStake) { address contractAddress; (validatorStake, , , , , , contractAddress, ) = IStakeManagerLocal( registry.getStakeManagerAddress() ) .validators(validatorId); if (contractAddress != address(0x0)) { validatorStake += IStakeManagerLocal(contractAddress).activeAmount(); } } function getAccountStateRoot() public view returns (bytes32 accountStateRoot) { accountStateRoot = IStakeManagerLocal(registry.getStakeManagerAddress()) .accountStateRoot(); } function getValidatorContractAddress(uint256 validatorId) public view returns (address ValidatorContract) { (, , , , , , ValidatorContract, ) = IStakeManagerLocal( registry.getStakeManagerAddress() ) .validators(validatorId); } // validator Share contract logging func function logShareMinted( uint256 validatorId, address user, uint256 amount, uint256 tokens ) public onlyValidatorContract(validatorId) { emit ShareMinted(validatorId, user, amount, tokens); } function logShareBurned( uint256 validatorId, address user, uint256 amount, uint256 tokens ) public onlyValidatorContract(validatorId) { emit ShareBurned(validatorId, user, amount, tokens); } function logDelegatorClaimRewards( uint256 validatorId, address user, uint256 rewards ) public onlyValidatorContract(validatorId) { emit DelegatorClaimedRewards(validatorId, user, rewards); } function logDelegatorRestaked( uint256 validatorId, address user, uint256 totalStaked ) public onlyValidatorContract(validatorId) { emit DelegatorRestaked(validatorId, user, totalStaked); } function logDelegatorUnstaked(uint256 validatorId, address user, uint256 amount) public onlyValidatorContract(validatorId) { emit DelegatorUnstaked(validatorId, user, amount); } // deprecated function logUpdateCommissionRate( uint256 validatorId, uint256 newCommissionRate, uint256 oldCommissionRate ) public onlyValidatorContract(validatorId) { emit UpdateCommissionRate( validatorId, newCommissionRate, oldCommissionRate ); } } // File: contracts/common/mixin/Initializable.sol pragma solidity ^0.5.2; contract Initializable { bool inited = false; modifier initializer() { require(!inited, "already inited"); inited = true; _; } } // File: contracts/staking/EventsHub.sol pragma solidity ^0.5.2; contract IStakeManagerEventsHub { struct Validator { uint256 amount; uint256 reward; uint256 activationEpoch; uint256 deactivationEpoch; uint256 jailTime; address signer; address contractAddress; } mapping(uint256 => Validator) public validators; } contract EventsHub is Initializable { Registry public registry; modifier onlyValidatorContract(uint256 validatorId) { address _contract; (, , , , , , _contract) = IStakeManagerEventsHub(registry.getStakeManagerAddress()).validators(validatorId); require(_contract == msg.sender, "not validator"); _; } modifier onlyStakeManager() { require(registry.getStakeManagerAddress() == msg.sender, "Invalid sender, not stake manager"); _; } function initialize(Registry _registry) external initializer { registry = _registry; } event ShareBurnedWithId( uint256 indexed validatorId, address indexed user, uint256 indexed amount, uint256 tokens, uint256 nonce ); function logShareBurnedWithId( uint256 validatorId, address user, uint256 amount, uint256 tokens, uint256 nonce ) public onlyValidatorContract(validatorId) { emit ShareBurnedWithId(validatorId, user, amount, tokens, nonce); } event DelegatorUnstakeWithId( uint256 indexed validatorId, address indexed user, uint256 amount, uint256 nonce ); function logDelegatorUnstakedWithId( uint256 validatorId, address user, uint256 amount, uint256 nonce ) public onlyValidatorContract(validatorId) { emit DelegatorUnstakeWithId(validatorId, user, amount, nonce); } event RewardParams( uint256 rewardDecreasePerCheckpoint, uint256 maxRewardedCheckpoints, uint256 checkpointRewardDelta ); function logRewardParams( uint256 rewardDecreasePerCheckpoint, uint256 maxRewardedCheckpoints, uint256 checkpointRewardDelta ) public onlyStakeManager { emit RewardParams(rewardDecreasePerCheckpoint, maxRewardedCheckpoints, checkpointRewardDelta); } event UpdateCommissionRate( uint256 indexed validatorId, uint256 indexed newCommissionRate, uint256 indexed oldCommissionRate ); function logUpdateCommissionRate( uint256 validatorId, uint256 newCommissionRate, uint256 oldCommissionRate ) public onlyStakeManager { emit UpdateCommissionRate( validatorId, newCommissionRate, oldCommissionRate ); } event SharesTransfer( uint256 indexed validatorId, address indexed from, address indexed to, uint256 value ); function logSharesTransfer( uint256 validatorId, address from, address to, uint256 value ) public onlyValidatorContract(validatorId) { emit SharesTransfer(validatorId, from, to, value); } } // File: contracts/common/mixin/OwnableLockable.sol pragma solidity ^0.5.2; contract OwnableLockable is Lockable, Ownable { function lock() public onlyOwner { super.lock(); } function unlock() public onlyOwner { super.unlock(); } } // File: contracts/staking/validatorShare/ValidatorShare.sol pragma solidity 0.5.17; contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, Initializable { struct DelegatorUnbond { uint256 shares; uint256 withdrawEpoch; } uint256 constant EXCHANGE_RATE_PRECISION = 100; // maximum matic possible, even if rate will be 1 and all matic will be staken in one go, it will result in 10 ^ 58 shares uint256 constant EXCHANGE_RATE_HIGH_PRECISION = 10**29; uint256 constant MAX_COMMISION_RATE = 100; uint256 constant REWARD_PRECISION = 10**25; StakingInfo public stakingLogger; IStakeManager public stakeManager; uint256 public validatorId; uint256 public validatorRewards_deprecated; uint256 public commissionRate_deprecated; uint256 public lastCommissionUpdate_deprecated; uint256 public minAmount; uint256 public totalStake_deprecated; uint256 public rewardPerShare; uint256 public activeAmount; bool public delegation; uint256 public withdrawPool; uint256 public withdrawShares; mapping(address => uint256) amountStaked_deprecated; // deprecated, keep for foundation delegators mapping(address => DelegatorUnbond) public unbonds; mapping(address => uint256) public initalRewardPerShare; mapping(address => uint256) public unbondNonces; mapping(address => mapping(uint256 => DelegatorUnbond)) public unbonds_new; EventsHub public eventsHub; // onlyOwner will prevent this contract from initializing, since it's owner is going to be 0x0 address function initialize( uint256 _validatorId, address _stakingLogger, address _stakeManager ) external initializer { validatorId = _validatorId; stakingLogger = StakingInfo(_stakingLogger); stakeManager = IStakeManager(_stakeManager); _transferOwnership(_stakeManager); _getOrCacheEventsHub(); minAmount = 10**18; delegation = true; } /** Public View Methods */ function exchangeRate() public view returns (uint256) { uint256 totalShares = totalSupply(); uint256 precision = _getRatePrecision(); return totalShares == 0 ? precision : stakeManager.delegatedAmount(validatorId).mul(precision).div(totalShares); } function getTotalStake(address user) public view returns (uint256, uint256) { uint256 shares = balanceOf(user); uint256 rate = exchangeRate(); if (shares == 0) { return (0, rate); } return (rate.mul(shares).div(_getRatePrecision()), rate); } function withdrawExchangeRate() public view returns (uint256) { uint256 precision = _getRatePrecision(); if (validatorId < 8) { // fix of potentially broken withdrawals for future unbonding // foundation validators have no slashing enabled and thus we can return default exchange rate // because without slashing rate will stay constant return precision; } uint256 _withdrawShares = withdrawShares; return _withdrawShares == 0 ? precision : withdrawPool.mul(precision).div(_withdrawShares); } function getLiquidRewards(address user) public view returns (uint256) { return _calculateReward(user, getRewardPerShare()); } function getRewardPerShare() public view returns (uint256) { return _calculateRewardPerShareWithRewards(stakeManager.delegatorsReward(validatorId)); } /** Public Methods */ function buyVoucher(uint256 _amount, uint256 _minSharesToMint) public returns(uint256 amountToDeposit) { _withdrawAndTransferReward(msg.sender); amountToDeposit = _buyShares(_amount, _minSharesToMint, msg.sender); require(stakeManager.delegationDeposit(validatorId, amountToDeposit, msg.sender), "deposit failed"); return amountToDeposit; } function restake() public returns(uint256, uint256) { address user = msg.sender; uint256 liquidReward = _withdrawReward(user); uint256 amountRestaked; require(liquidReward >= minAmount, "Too small rewards to restake"); if (liquidReward != 0) { amountRestaked = _buyShares(liquidReward, 0, user); if (liquidReward > amountRestaked) { // return change to the user require( stakeManager.transferFunds(validatorId, liquidReward - amountRestaked, user), "Insufficent rewards" ); stakingLogger.logDelegatorClaimRewards(validatorId, user, liquidReward - amountRestaked); } (uint256 totalStaked, ) = getTotalStake(user); stakingLogger.logDelegatorRestaked(validatorId, user, totalStaked); } return (amountRestaked, liquidReward); } function sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn) public { (uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn); DelegatorUnbond memory unbond = unbonds[msg.sender]; unbond.shares = unbond.shares.add(_withdrawPoolShare); // refresh undond period unbond.withdrawEpoch = stakeManager.epoch(); unbonds[msg.sender] = unbond; StakingInfo logger = stakingLogger; logger.logShareBurned(validatorId, msg.sender, claimAmount, shares); logger.logStakeUpdate(validatorId); } function withdrawRewards() public { uint256 rewards = _withdrawAndTransferReward(msg.sender); require(rewards >= minAmount, "Too small rewards amount"); } function migrateOut(address user, uint256 amount) external onlyOwner { _withdrawAndTransferReward(user); (uint256 totalStaked, uint256 rate) = getTotalStake(user); require(totalStaked >= amount, "Migrating too much"); uint256 precision = _getRatePrecision(); uint256 shares = amount.mul(precision).div(rate); _burn(user, shares); stakeManager.updateValidatorState(validatorId, -int256(amount)); activeAmount = activeAmount.sub(amount); stakingLogger.logShareBurned(validatorId, user, amount, shares); stakingLogger.logStakeUpdate(validatorId); stakingLogger.logDelegatorUnstaked(validatorId, user, amount); } function migrateIn(address user, uint256 amount) external onlyOwner { _withdrawAndTransferReward(user); _buyShares(amount, 0, user); } function unstakeClaimTokens() public { DelegatorUnbond memory unbond = unbonds[msg.sender]; uint256 amount = _unstakeClaimTokens(unbond); delete unbonds[msg.sender]; stakingLogger.logDelegatorUnstaked(validatorId, msg.sender, amount); } function slash( uint256 validatorStake, uint256 delegatedAmount, uint256 totalAmountToSlash ) external onlyOwner returns (uint256) { uint256 _withdrawPool = withdrawPool; uint256 delegationAmount = delegatedAmount.add(_withdrawPool); if (delegationAmount == 0) { return 0; } // total amount to be slashed from delegation pool (active + inactive) uint256 _amountToSlash = delegationAmount.mul(totalAmountToSlash).div(validatorStake.add(delegationAmount)); uint256 _amountToSlashWithdrawalPool = _withdrawPool.mul(_amountToSlash).div(delegationAmount); // slash inactive pool uint256 stakeSlashed = _amountToSlash.sub(_amountToSlashWithdrawalPool); stakeManager.decreaseValidatorDelegatedAmount(validatorId, stakeSlashed); activeAmount = activeAmount.sub(stakeSlashed); withdrawPool = withdrawPool.sub(_amountToSlashWithdrawalPool); return _amountToSlash; } function updateDelegation(bool _delegation) external onlyOwner { delegation = _delegation; } function drain( address token, address payable destination, uint256 amount ) external onlyOwner { if (token == address(0x0)) { destination.transfer(amount); } else { require(ERC20(token).transfer(destination, amount), "Drain failed"); } } /** New shares exit API */ function sellVoucher_new(uint256 claimAmount, uint256 maximumSharesToBurn) public { (uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn); uint256 unbondNonce = unbondNonces[msg.sender].add(1); DelegatorUnbond memory unbond = DelegatorUnbond({ shares: _withdrawPoolShare, withdrawEpoch: stakeManager.epoch() }); unbonds_new[msg.sender][unbondNonce] = unbond; unbondNonces[msg.sender] = unbondNonce; _getOrCacheEventsHub().logShareBurnedWithId(validatorId, msg.sender, claimAmount, shares, unbondNonce); stakingLogger.logStakeUpdate(validatorId); } function unstakeClaimTokens_new(uint256 unbondNonce) public { DelegatorUnbond memory unbond = unbonds_new[msg.sender][unbondNonce]; uint256 amount = _unstakeClaimTokens(unbond); delete unbonds_new[msg.sender][unbondNonce]; _getOrCacheEventsHub().logDelegatorUnstakedWithId(validatorId, msg.sender, amount, unbondNonce); } /** Private Methods */ function _getOrCacheEventsHub() private returns(EventsHub) { EventsHub _eventsHub = eventsHub; if (_eventsHub == EventsHub(0x0)) { _eventsHub = EventsHub(Registry(stakeManager.getRegistry()).contractMap(keccak256("eventsHub"))); eventsHub = _eventsHub; } return _eventsHub; } function _sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn) private returns(uint256, uint256) { // first get how much staked in total and compare to target unstake amount (uint256 totalStaked, uint256 rate) = getTotalStake(msg.sender); require(totalStaked != 0 && totalStaked >= claimAmount, "Too much requested"); // convert requested amount back to shares uint256 precision = _getRatePrecision(); uint256 shares = claimAmount.mul(precision).div(rate); require(shares <= maximumSharesToBurn, "too much slippage"); _withdrawAndTransferReward(msg.sender); _burn(msg.sender, shares); stakeManager.updateValidatorState(validatorId, -int256(claimAmount)); activeAmount = activeAmount.sub(claimAmount); uint256 _withdrawPoolShare = claimAmount.mul(precision).div(withdrawExchangeRate()); withdrawPool = withdrawPool.add(claimAmount); withdrawShares = withdrawShares.add(_withdrawPoolShare); return (shares, _withdrawPoolShare); } function _unstakeClaimTokens(DelegatorUnbond memory unbond) private returns(uint256) { uint256 shares = unbond.shares; require( unbond.withdrawEpoch.add(stakeManager.withdrawalDelay()) <= stakeManager.epoch() && shares > 0, "Incomplete withdrawal period" ); uint256 _amount = withdrawExchangeRate().mul(shares).div(_getRatePrecision()); withdrawShares = withdrawShares.sub(shares); withdrawPool = withdrawPool.sub(_amount); require(stakeManager.transferFunds(validatorId, _amount, msg.sender), "Insufficent rewards"); return _amount; } function _getRatePrecision() private view returns (uint256) { // if foundation validator, use old precision if (validatorId < 8) { return EXCHANGE_RATE_PRECISION; } return EXCHANGE_RATE_HIGH_PRECISION; } function _calculateRewardPerShareWithRewards(uint256 accumulatedReward) private view returns (uint256) { uint256 _rewardPerShare = rewardPerShare; if (accumulatedReward != 0) { uint256 totalShares = totalSupply(); if (totalShares != 0) { _rewardPerShare = _rewardPerShare.add(accumulatedReward.mul(REWARD_PRECISION).div(totalShares)); } } return _rewardPerShare; } function _calculateReward(address user, uint256 _rewardPerShare) private view returns (uint256) { uint256 shares = balanceOf(user); if (shares == 0) { return 0; } uint256 _initialRewardPerShare = initalRewardPerShare[user]; if (_initialRewardPerShare == _rewardPerShare) { return 0; } return _rewardPerShare.sub(_initialRewardPerShare).mul(shares).div(REWARD_PRECISION); } function _withdrawReward(address user) private returns (uint256) { uint256 _rewardPerShare = _calculateRewardPerShareWithRewards( stakeManager.withdrawDelegatorsReward(validatorId) ); uint256 liquidRewards = _calculateReward(user, _rewardPerShare); rewardPerShare = _rewardPerShare; initalRewardPerShare[user] = _rewardPerShare; return liquidRewards; } function _withdrawAndTransferReward(address user) private returns (uint256) { uint256 liquidRewards = _withdrawReward(user); if (liquidRewards != 0) { require(stakeManager.transferFunds(validatorId, liquidRewards, user), "Insufficent rewards"); stakingLogger.logDelegatorClaimRewards(validatorId, user, liquidRewards); } return liquidRewards; } function _buyShares( uint256 _amount, uint256 _minSharesToMint, address user ) private onlyWhenUnlocked returns (uint256) { require(delegation, "Delegation is disabled"); uint256 rate = exchangeRate(); uint256 precision = _getRatePrecision(); uint256 shares = _amount.mul(precision).div(rate); require(shares >= _minSharesToMint, "Too much slippage"); require(unbonds[user].shares == 0, "Ongoing exit"); _mint(user, shares); // clamp amount of tokens in case resulted shares requires less tokens than anticipated _amount = rate.mul(shares).div(precision); stakeManager.updateValidatorState(validatorId, int256(_amount)); activeAmount = activeAmount.add(_amount); StakingInfo logger = stakingLogger; logger.logShareMinted(validatorId, user, _amount, shares); logger.logStakeUpdate(validatorId); return _amount; } function _transfer( address from, address to, uint256 value ) internal { // get rewards for recipient _withdrawAndTransferReward(to); // convert rewards to shares _withdrawAndTransferReward(from); // move shares to recipient super._transfer(from, to, value); _getOrCacheEventsHub().logSharesTransfer(validatorId, from, to, value); } } // File: openzeppelin-solidity/contracts/introspection/IERC165.sol pragma solidity ^0.5.2; /** * @title IERC165 * @dev https://eips.ethereum.org/EIPS/eip-165 */ interface IERC165 { /** * @notice Query if a contract implements an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @dev Interface identification is specified in ERC-165. This function * uses less than 30,000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: openzeppelin-solidity/contracts/token/ERC721/IERC721.sol pragma solidity ^0.5.2; /** * @title ERC721 Non-Fungible Token Standard basic interface * @dev see https://eips.ethereum.org/EIPS/eip-721 */ contract IERC721 is IERC165 { event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); function balanceOf(address owner) public view returns (uint256 balance); function ownerOf(uint256 tokenId) public view returns (address owner); function approve(address to, uint256 tokenId) public; function getApproved(uint256 tokenId) public view returns (address operator); function setApprovalForAll(address operator, bool _approved) public; function isApprovedForAll(address owner, address operator) public view returns (bool); function transferFrom(address from, address to, uint256 tokenId) public; function safeTransferFrom(address from, address to, uint256 tokenId) public; function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public; } // File: openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol pragma solidity ^0.5.2; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ contract IERC721Receiver { /** * @notice Handle the receipt of an NFT * @dev The ERC721 smart contract calls this function on the recipient * after a `safeTransfer`. This function MUST return the function selector, * otherwise the caller will revert the transaction. The selector to be * returned can be obtained as `this.onERC721Received.selector`. This * function MAY throw to revert and reject the transfer. * Note: the ERC721 contract address is always the message sender. * @param operator The address which called `safeTransferFrom` function * @param from The address which previously owned the token * @param tokenId The NFT identifier which is being transferred * @param data Additional data with no specified format * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` */ function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) public returns (bytes4); } // File: openzeppelin-solidity/contracts/utils/Address.sol pragma solidity ^0.5.2; /** * Utility library of inline functions on addresses */ library Address { /** * Returns whether the target address is a contract * @dev This function will return false if invoked during the constructor of a contract, * as the code is not actually created until after the constructor finishes. * @param account address of the account to check * @return whether the target address is a contract */ function isContract(address account) internal view returns (bool) { uint256 size; // XXX Currently there is no better way to check if there is a contract in an address // than to check the size of the code at that address. // See https://ethereum.stackexchange.com/a/14016/36603 // for more details about how this works. // TODO Check this again before the Serenity release, because all addresses will be // contracts then. // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } } // File: openzeppelin-solidity/contracts/drafts/Counters.sol pragma solidity ^0.5.2; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids * * Include with `using Counters for Counters.Counter;` * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the SafeMath * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never * directly accessed. */ library Counters { using SafeMath for uint256; struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { counter._value += 1; } function decrement(Counter storage counter) internal { counter._value = counter._value.sub(1); } } // File: openzeppelin-solidity/contracts/introspection/ERC165.sol pragma solidity ^0.5.2; /** * @title ERC165 * @author Matt Condon (@shrugs) * @dev Implements ERC165 using a lookup table. */ contract ERC165 is IERC165 { bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /* * 0x01ffc9a7 === * bytes4(keccak256('supportsInterface(bytes4)')) */ /** * @dev a mapping of interface id to whether or not it's supported */ mapping(bytes4 => bool) private _supportedInterfaces; /** * @dev A contract implementing SupportsInterfaceWithLookup * implement ERC165 itself */ constructor () internal { _registerInterface(_INTERFACE_ID_ERC165); } /** * @dev implement supportsInterface(bytes4) using a lookup table */ function supportsInterface(bytes4 interfaceId) external view returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev internal method for registering an interface */ function _registerInterface(bytes4 interfaceId) internal { require(interfaceId != 0xffffffff); _supportedInterfaces[interfaceId] = true; } } // File: openzeppelin-solidity/contracts/token/ERC721/ERC721.sol pragma solidity ^0.5.2; /** * @title ERC721 Non-Fungible Token Standard basic implementation * @dev see https://eips.ethereum.org/EIPS/eip-721 */ contract ERC721 is ERC165, IERC721 { using SafeMath for uint256; using Address for address; using Counters for Counters.Counter; // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; // Mapping from token ID to owner mapping (uint256 => address) private _tokenOwner; // Mapping from token ID to approved address mapping (uint256 => address) private _tokenApprovals; // Mapping from owner to number of owned token mapping (address => Counters.Counter) private _ownedTokensCount; // Mapping from owner to operator approvals mapping (address => mapping (address => bool)) private _operatorApprovals; bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; /* * 0x80ac58cd === * bytes4(keccak256('balanceOf(address)')) ^ * bytes4(keccak256('ownerOf(uint256)')) ^ * bytes4(keccak256('approve(address,uint256)')) ^ * bytes4(keccak256('getApproved(uint256)')) ^ * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ * bytes4(keccak256('isApprovedForAll(address,address)')) ^ * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) */ constructor () public { // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(_INTERFACE_ID_ERC721); } /** * @dev Gets the balance of the specified address * @param owner address to query the balance of * @return uint256 representing the amount owned by the passed address */ function balanceOf(address owner) public view returns (uint256) { require(owner != address(0)); return _ownedTokensCount[owner].current(); } /** * @dev Gets the owner of the specified token ID * @param tokenId uint256 ID of the token to query the owner of * @return address currently marked as the owner of the given token ID */ function ownerOf(uint256 tokenId) public view returns (address) { address owner = _tokenOwner[tokenId]; require(owner != address(0)); return owner; } /** * @dev Approves another address to transfer the given token ID * The zero address indicates there is no approved address. * There can only be one approved address per token at a given time. * Can only be called by the token owner or an approved operator. * @param to address to be approved for the given token ID * @param tokenId uint256 ID of the token to be approved */ function approve(address to, uint256 tokenId) public { address owner = ownerOf(tokenId); require(to != owner); require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); _tokenApprovals[tokenId] = to; emit Approval(owner, to, tokenId); } /** * @dev Gets the approved address for a token ID, or zero if no address set * Reverts if the token ID does not exist. * @param tokenId uint256 ID of the token to query the approval of * @return address currently approved for the given token ID */ function getApproved(uint256 tokenId) public view returns (address) { require(_exists(tokenId)); return _tokenApprovals[tokenId]; } /** * @dev Sets or unsets the approval of a given operator * An operator is allowed to transfer all tokens of the sender on their behalf * @param to operator address to set the approval * @param approved representing the status of the approval to be set */ function setApprovalForAll(address to, bool approved) public { require(to != msg.sender); _operatorApprovals[msg.sender][to] = approved; emit ApprovalForAll(msg.sender, to, approved); } /** * @dev Tells whether an operator is approved by a given owner * @param owner owner address which you want to query the approval of * @param operator operator address which you want to query the approval of * @return bool whether the given operator is approved by the given owner */ function isApprovedForAll(address owner, address operator) public view returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev Transfers the ownership of a given token ID to another address * Usage of this method is discouraged, use `safeTransferFrom` whenever possible * Requires the msg.sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function transferFrom(address from, address to, uint256 tokenId) public { require(_isApprovedOrOwner(msg.sender, tokenId)); _transferFrom(from, to, tokenId); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement `onERC721Received`, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the msg.sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function safeTransferFrom(address from, address to, uint256 tokenId) public { safeTransferFrom(from, to, tokenId, ""); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement `onERC721Received`, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the msg.sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred * @param _data bytes data to send along with a safe transfer check */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public { transferFrom(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, _data)); } /** * @dev Returns whether the specified token exists * @param tokenId uint256 ID of the token to query the existence of * @return bool whether the token exists */ function _exists(uint256 tokenId) internal view returns (bool) { address owner = _tokenOwner[tokenId]; return owner != address(0); } /** * @dev Returns whether the given spender can transfer a given token ID * @param spender address of the spender to query * @param tokenId uint256 ID of the token to be transferred * @return bool whether the msg.sender is approved for the given token ID, * is an operator of the owner, or is the owner of the token */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { address owner = ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } /** * @dev Internal function to mint a new token * Reverts if the given token ID already exists * @param to The address that will own the minted token * @param tokenId uint256 ID of the token to be minted */ function _mint(address to, uint256 tokenId) internal { require(to != address(0)); require(!_exists(tokenId)); _tokenOwner[tokenId] = to; _ownedTokensCount[to].increment(); emit Transfer(address(0), to, tokenId); } /** * @dev Internal function to burn a specific token * Reverts if the token does not exist * Deprecated, use _burn(uint256) instead. * @param owner owner of the token to burn * @param tokenId uint256 ID of the token being burned */ function _burn(address owner, uint256 tokenId) internal { require(ownerOf(tokenId) == owner); _clearApproval(tokenId); _ownedTokensCount[owner].decrement(); _tokenOwner[tokenId] = address(0); emit Transfer(owner, address(0), tokenId); } /** * @dev Internal function to burn a specific token * Reverts if the token does not exist * @param tokenId uint256 ID of the token being burned */ function _burn(uint256 tokenId) internal { _burn(ownerOf(tokenId), tokenId); } /** * @dev Internal function to transfer ownership of a given token ID to another address. * As opposed to transferFrom, this imposes no restrictions on msg.sender. * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function _transferFrom(address from, address to, uint256 tokenId) internal { require(ownerOf(tokenId) == from); require(to != address(0)); _clearApproval(tokenId); _ownedTokensCount[from].decrement(); _ownedTokensCount[to].increment(); _tokenOwner[tokenId] = to; emit Transfer(from, to, tokenId); } /** * @dev Internal function to invoke `onERC721Received` on a target address * The call is not executed if the target address is not a contract * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) internal returns (bool) { if (!to.isContract()) { return true; } bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data); return (retval == _ERC721_RECEIVED); } /** * @dev Private function to clear current approval of a given token ID * @param tokenId uint256 ID of the token to be transferred */ function _clearApproval(uint256 tokenId) private { if (_tokenApprovals[tokenId] != address(0)) { _tokenApprovals[tokenId] = address(0); } } } // File: openzeppelin-solidity/contracts/token/ERC721/IERC721Enumerable.sol pragma solidity ^0.5.2; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ contract IERC721Enumerable is IERC721 { function totalSupply() public view returns (uint256); function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256 tokenId); function tokenByIndex(uint256 index) public view returns (uint256); } // File: openzeppelin-solidity/contracts/token/ERC721/ERC721Enumerable.sol pragma solidity ^0.5.2; /** * @title ERC-721 Non-Fungible Token with optional enumeration extension logic * @dev See https://eips.ethereum.org/EIPS/eip-721 */ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => uint256[]) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; /* * 0x780e9d63 === * bytes4(keccak256('totalSupply()')) ^ * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ * bytes4(keccak256('tokenByIndex(uint256)')) */ /** * @dev Constructor function */ constructor () public { // register the supported interface to conform to ERC721Enumerable via ERC165 _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE); } /** * @dev Gets the token ID at a given index of the tokens list of the requested owner * @param owner address owning the tokens list to be accessed * @param index uint256 representing the index to be accessed of the requested tokens list * @return uint256 token ID at the given index of the tokens list owned by the requested address */ function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) { require(index < balanceOf(owner)); return _ownedTokens[owner][index]; } /** * @dev Gets the total amount of tokens stored by the contract * @return uint256 representing the total amount of tokens */ function totalSupply() public view returns (uint256) { return _allTokens.length; } /** * @dev Gets the token ID at a given index of all the tokens in this contract * Reverts if the index is greater or equal to the total number of tokens * @param index uint256 representing the index to be accessed of the tokens list * @return uint256 token ID at the given index of the tokens list */ function tokenByIndex(uint256 index) public view returns (uint256) { require(index < totalSupply()); return _allTokens[index]; } /** * @dev Internal function to transfer ownership of a given token ID to another address. * As opposed to transferFrom, this imposes no restrictions on msg.sender. * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function _transferFrom(address from, address to, uint256 tokenId) internal { super._transferFrom(from, to, tokenId); _removeTokenFromOwnerEnumeration(from, tokenId); _addTokenToOwnerEnumeration(to, tokenId); } /** * @dev Internal function to mint a new token * Reverts if the given token ID already exists * @param to address the beneficiary that will own the minted token * @param tokenId uint256 ID of the token to be minted */ function _mint(address to, uint256 tokenId) internal { super._mint(to, tokenId); _addTokenToOwnerEnumeration(to, tokenId); _addTokenToAllTokensEnumeration(tokenId); } /** * @dev Internal function to burn a specific token * Reverts if the token does not exist * Deprecated, use _burn(uint256) instead * @param owner owner of the token to burn * @param tokenId uint256 ID of the token being burned */ function _burn(address owner, uint256 tokenId) internal { super._burn(owner, tokenId); _removeTokenFromOwnerEnumeration(owner, tokenId); // Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund _ownedTokensIndex[tokenId] = 0; _removeTokenFromAllTokensEnumeration(tokenId); } /** * @dev Gets the list of token IDs of the requested owner * @param owner address owning the tokens * @return uint256[] List of token IDs owned by the requested address */ function _tokensOfOwner(address owner) internal view returns (uint256[] storage) { return _ownedTokens[owner]; } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { _ownedTokensIndex[tokenId] = _ownedTokens[to].length; _ownedTokens[to].push(tokenId); } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the _ownedTokensIndex mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array _ownedTokens[from].length--; // Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occupied by // lastTokenId, or just over the end of the array if the token was the last one). } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length.sub(1); uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array _allTokens.length--; _allTokensIndex[tokenId] = 0; } } // File: openzeppelin-solidity/contracts/token/ERC721/IERC721Metadata.sol pragma solidity ^0.5.2; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ contract IERC721Metadata is IERC721 { function name() external view returns (string memory); function symbol() external view returns (string memory); function tokenURI(uint256 tokenId) external view returns (string memory); } // File: openzeppelin-solidity/contracts/token/ERC721/ERC721Metadata.sol pragma solidity ^0.5.2; contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { // Token name string private _name; // Token symbol string private _symbol; // Optional mapping for token URIs mapping(uint256 => string) private _tokenURIs; bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f; /* * 0x5b5e139f === * bytes4(keccak256('name()')) ^ * bytes4(keccak256('symbol()')) ^ * bytes4(keccak256('tokenURI(uint256)')) */ /** * @dev Constructor function */ constructor (string memory name, string memory symbol) public { _name = name; _symbol = symbol; // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(_INTERFACE_ID_ERC721_METADATA); } /** * @dev Gets the token name * @return string representing the token name */ function name() external view returns (string memory) { return _name; } /** * @dev Gets the token symbol * @return string representing the token symbol */ function symbol() external view returns (string memory) { return _symbol; } /** * @dev Returns an URI for a given token ID * Throws if the token ID does not exist. May return an empty string. * @param tokenId uint256 ID of the token to query */ function tokenURI(uint256 tokenId) external view returns (string memory) { require(_exists(tokenId)); return _tokenURIs[tokenId]; } /** * @dev Internal function to set the token URI for a given token * Reverts if the token ID does not exist * @param tokenId uint256 ID of the token to set its URI * @param uri string URI to assign */ function _setTokenURI(uint256 tokenId, string memory uri) internal { require(_exists(tokenId)); _tokenURIs[tokenId] = uri; } /** * @dev Internal function to burn a specific token * Reverts if the token does not exist * Deprecated, use _burn(uint256) instead * @param owner owner of the token to burn * @param tokenId uint256 ID of the token being burned by the msg.sender */ function _burn(address owner, uint256 tokenId) internal { super._burn(owner, tokenId); // Clear metadata (if any) if (bytes(_tokenURIs[tokenId]).length != 0) { delete _tokenURIs[tokenId]; } } } // File: openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol pragma solidity ^0.5.2; /** * @title Full ERC721 Token * This implementation includes all the required and some optional functionality of the ERC721 standard * Moreover, it includes approve all functionality using operator terminology * @dev see https://eips.ethereum.org/EIPS/eip-721 */ contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata { constructor (string memory name, string memory symbol) public ERC721Metadata(name, symbol) { // solhint-disable-previous-line no-empty-blocks } } // File: contracts/staking/stakeManager/StakingNFT.sol pragma solidity ^0.5.2; contract StakingNFT is ERC721Full, Ownable { constructor(string memory name, string memory symbol) public ERC721Full(name, symbol) { // solhint-disable-previous-line no-empty-blocks } function mint(address to, uint256 tokenId) public onlyOwner { require( balanceOf(to) == 0, "Validators MUST NOT own multiple stake position" ); _mint(to, tokenId); } function burn(uint256 tokenId) public onlyOwner { _burn(tokenId); } function _transferFrom(address from, address to, uint256 tokenId) internal { require( balanceOf(to) == 0, "Validators MUST NOT own multiple stake position" ); super._transferFrom(from, to, tokenId); } } // File: contracts/common/misc/ERCProxy.sol /* * SPDX-License-Identitifer: MIT */ pragma solidity ^0.5.2; // See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-897.md interface ERCProxy { function proxyType() external pure returns (uint256 proxyTypeId); function implementation() external view returns (address codeAddr); } // File: contracts/common/misc/DelegateProxy.sol pragma solidity ^0.5.2; contract DelegateProxy is ERCProxy, DelegateProxyForwarder { function proxyType() external pure returns (uint256 proxyTypeId) { // Upgradeable proxy proxyTypeId = 2; } function implementation() external view returns (address); } // File: contracts/common/misc/UpgradableProxy.sol pragma solidity ^0.5.2; contract UpgradableProxy is DelegateProxy { event ProxyUpdated(address indexed _new, address indexed _old); event OwnerUpdate(address _new, address _old); bytes32 constant IMPLEMENTATION_SLOT = keccak256("matic.network.proxy.implementation"); bytes32 constant OWNER_SLOT = keccak256("matic.network.proxy.owner"); constructor(address _proxyTo) public { setOwner(msg.sender); setImplementation(_proxyTo); } function() external payable { // require(currentContract != 0, "If app code has not been set yet, do not call"); // Todo: filter out some calls or handle in the end fallback delegatedFwd(loadImplementation(), msg.data); } modifier onlyProxyOwner() { require(loadOwner() == msg.sender, "NOT_OWNER"); _; } function owner() external view returns(address) { return loadOwner(); } function loadOwner() internal view returns(address) { address _owner; bytes32 position = OWNER_SLOT; assembly { _owner := sload(position) } return _owner; } function implementation() external view returns (address) { return loadImplementation(); } function loadImplementation() internal view returns(address) { address _impl; bytes32 position = IMPLEMENTATION_SLOT; assembly { _impl := sload(position) } return _impl; } function transferOwnership(address newOwner) public onlyProxyOwner { require(newOwner != address(0), "ZERO_ADDRESS"); emit OwnerUpdate(newOwner, loadOwner()); setOwner(newOwner); } function setOwner(address newOwner) private { bytes32 position = OWNER_SLOT; assembly { sstore(position, newOwner) } } function updateImplementation(address _newProxyTo) public onlyProxyOwner { require(_newProxyTo != address(0x0), "INVALID_PROXY_ADDRESS"); require(isContract(_newProxyTo), "DESTINATION_ADDRESS_IS_NOT_A_CONTRACT"); emit ProxyUpdated(_newProxyTo, loadImplementation()); setImplementation(_newProxyTo); } function updateAndCall(address _newProxyTo, bytes memory data) payable public onlyProxyOwner { updateImplementation(_newProxyTo); (bool success, bytes memory returnData) = address(this).call.value(msg.value)(data); require(success, string(returnData)); } function setImplementation(address _newProxyTo) private { bytes32 position = IMPLEMENTATION_SLOT; assembly { sstore(position, _newProxyTo) } } } // File: contracts/staking/validatorShare/ValidatorShareProxy.sol pragma solidity ^0.5.2; contract ValidatorShareProxy is UpgradableProxy { constructor(address _registry) public UpgradableProxy(_registry) {} function loadImplementation() internal view returns (address) { return Registry(super.loadImplementation()).getValidatorShareAddress(); } } // File: contracts/staking/validatorShare/ValidatorShareFactory.sol pragma solidity ^0.5.2; contract ValidatorShareFactory { /** - factory to create new validatorShare contracts */ function create(uint256 validatorId, address loggerAddress, address registry) public returns (address) { ValidatorShareProxy proxy = new ValidatorShareProxy(registry); proxy.transferOwnership(msg.sender); address proxyAddr = address(proxy); (bool success, bytes memory data) = proxyAddr.call.gas(gasleft())( abi.encodeWithSelector( ValidatorShare(proxyAddr).initialize.selector, validatorId, loggerAddress, msg.sender ) ); require(success, string(data)); return proxyAddr; } } // File: contracts/common/mixin/RootChainable.sol pragma solidity ^0.5.2; /** * @title RootChainable */ contract RootChainable is Ownable { address public rootChain; // Rootchain changed event RootChainChanged( address indexed previousRootChain, address indexed newRootChain ); // only root chain modifier onlyRootChain() { require(msg.sender == rootChain); _; } /** * @dev Allows the current owner to change root chain address. * @param newRootChain The address to new rootchain. */ function changeRootChain(address newRootChain) public onlyOwner { require(newRootChain != address(0)); emit RootChainChanged(rootChain, newRootChain); rootChain = newRootChain; } } // File: contracts/staking/stakeManager/StakeManagerStorage.sol pragma solidity 0.5.17; contract StakeManagerStorage is GovernanceLockable, RootChainable { enum Status {Inactive, Active, Locked, Unstaked} struct Auction { uint256 amount; uint256 startEpoch; address user; bool acceptDelegation; bytes signerPubkey; } struct State { uint256 amount; uint256 stakerCount; } struct StateChange { int256 amount; int256 stakerCount; } struct Validator { uint256 amount; uint256 reward; uint256 activationEpoch; uint256 deactivationEpoch; uint256 jailTime; address signer; address contractAddress; Status status; uint256 commissionRate; uint256 lastCommissionUpdate; uint256 delegatorsReward; uint256 delegatedAmount; uint256 initialRewardPerStake; } uint256 constant MAX_COMMISION_RATE = 100; uint256 constant MAX_PROPOSER_BONUS = 100; uint256 constant REWARD_PRECISION = 10**25; uint256 internal constant INCORRECT_VALIDATOR_ID = 2**256 - 1; uint256 internal constant INITIALIZED_AMOUNT = 1; IERC20 public token; address public registry; StakingInfo public logger; StakingNFT public NFTContract; ValidatorShareFactory public validatorShareFactory; uint256 public WITHDRAWAL_DELAY; // unit: epoch uint256 public currentEpoch; // genesis/governance variables uint256 public dynasty; // unit: epoch 50 days uint256 public CHECKPOINT_REWARD; // update via governance uint256 public minDeposit; // in ERC20 token uint256 public minHeimdallFee; // in ERC20 token uint256 public checkPointBlockInterval; uint256 public signerUpdateLimit; uint256 public validatorThreshold; //128 uint256 public totalStaked; uint256 public NFTCounter; uint256 public totalRewards; uint256 public totalRewardsLiquidated; uint256 public auctionPeriod; // 1 week in epochs uint256 public proposerBonus; // 10 % of total rewards bytes32 public accountStateRoot; // Stop validator auction for some time when updating dynasty value uint256 public replacementCoolDown; bool public delegationEnabled; mapping(uint256 => Validator) public validators; mapping(address => uint256) public signerToValidator; // current epoch stake power and stakers count State public validatorState; mapping(uint256 => StateChange) public validatorStateChanges; mapping(address => uint256) public userFeeExit; //Ongoing auctions for validatorId mapping(uint256 => Auction) public validatorAuction; // validatorId to last signer update epoch mapping(uint256 => uint256) public latestSignerUpdateEpoch; uint256 public totalHeimdallFee; } // File: contracts/staking/stakeManager/StakeManagerStorageExtension.sol pragma solidity 0.5.17; contract StakeManagerStorageExtension { address public eventsHub; uint256 public rewardPerStake; address public extensionCode; address[] public signers; uint256 constant CHK_REWARD_PRECISION = 100; uint256 public prevBlockInterval; // how much less reward per skipped checkpoint, 0 - 100% uint256 public rewardDecreasePerCheckpoint; // how many checkpoints to reward uint256 public maxRewardedCheckpoints; // increase / decrease value for faster or slower checkpoints, 0 - 100% uint256 public checkpointRewardDelta; } // File: contracts/staking/stakeManager/StakeManagerExtension.sol pragma solidity 0.5.17; contract StakeManagerExtension is StakeManagerStorage, Initializable, StakeManagerStorageExtension { using SafeMath for uint256; constructor() public GovernanceLockable(address(0x0)) {} function startAuction( uint256 validatorId, uint256 amount, bool _acceptDelegation, bytes calldata _signerPubkey ) external { uint256 currentValidatorAmount = validators[validatorId].amount; require( validators[validatorId].deactivationEpoch == 0 && currentValidatorAmount != 0, "Invalid validator for an auction" ); uint256 senderValidatorId = signerToValidator[msg.sender]; // make sure that signer wasn't used already require( NFTContract.balanceOf(msg.sender) == 0 && // existing validators can't bid senderValidatorId != INCORRECT_VALIDATOR_ID, "Already used address" ); uint256 _currentEpoch = currentEpoch; uint256 _replacementCoolDown = replacementCoolDown; // when dynasty period is updated validators are in cooldown period require(_replacementCoolDown == 0 || _replacementCoolDown <= _currentEpoch, "Cooldown period"); // (auctionPeriod--dynasty)--(auctionPeriod--dynasty)--(auctionPeriod--dynasty) // if it's auctionPeriod then will get residue smaller then auctionPeriod // from (CurrentPeriod of validator )%(auctionPeriod--dynasty) // make sure that its `auctionPeriod` window // dynasty = 30, auctionPeriod = 7, activationEpoch = 1, currentEpoch = 39 // residue 1 = (39-1)% (7+30), if residue <= auctionPeriod it's `auctionPeriod` require( (_currentEpoch.sub(validators[validatorId].activationEpoch) % dynasty.add(auctionPeriod)) < auctionPeriod, "Invalid auction period" ); uint256 perceivedStake = currentValidatorAmount; perceivedStake = perceivedStake.add(validators[validatorId].delegatedAmount); Auction storage auction = validatorAuction[validatorId]; uint256 currentAuctionAmount = auction.amount; perceivedStake = Math.max(perceivedStake, currentAuctionAmount); require(perceivedStake < amount, "Must bid higher"); require(token.transferFrom(msg.sender, address(this), amount), "Transfer failed"); //replace prev auction if (currentAuctionAmount != 0) { require(token.transfer(auction.user, currentAuctionAmount), "Bid return failed"); } // create new auction auction.amount = amount; auction.user = msg.sender; auction.acceptDelegation = _acceptDelegation; auction.signerPubkey = _signerPubkey; logger.logStartAuction(validatorId, currentValidatorAmount, amount); } function confirmAuctionBid( uint256 validatorId, uint256 heimdallFee, /** for new validator */ IStakeManager stakeManager ) external { Auction storage auction = validatorAuction[validatorId]; address auctionUser = auction.user; require( msg.sender == auctionUser || NFTContract.tokenOfOwnerByIndex(msg.sender, 0) == validatorId, "Only bidder can confirm" ); uint256 _currentEpoch = currentEpoch; require( _currentEpoch.sub(auction.startEpoch) % auctionPeriod.add(dynasty) >= auctionPeriod, "Not allowed before auctionPeriod" ); require(auction.user != address(0x0), "Invalid auction"); uint256 validatorAmount = validators[validatorId].amount; uint256 perceivedStake = validatorAmount; uint256 auctionAmount = auction.amount; perceivedStake = perceivedStake.add(validators[validatorId].delegatedAmount); // validator is last auctioner if (perceivedStake >= auctionAmount && validators[validatorId].deactivationEpoch == 0) { require(token.transfer(auctionUser, auctionAmount), "Bid return failed"); //cleanup auction data auction.startEpoch = _currentEpoch; logger.logConfirmAuction(validatorId, validatorId, validatorAmount); } else { stakeManager.dethroneAndStake( auctionUser, heimdallFee, validatorId, auctionAmount, auction.acceptDelegation, auction.signerPubkey ); } uint256 startEpoch = auction.startEpoch; delete validatorAuction[validatorId]; validatorAuction[validatorId].startEpoch = startEpoch; } function migrateValidatorsData(uint256 validatorIdFrom, uint256 validatorIdTo) external { for (uint256 i = validatorIdFrom; i < validatorIdTo; ++i) { ValidatorShare contractAddress = ValidatorShare(validators[i].contractAddress); if (contractAddress != ValidatorShare(0)) { // move validator rewards out from ValidatorShare contract validators[i].reward = contractAddress.validatorRewards_deprecated().add(INITIALIZED_AMOUNT); validators[i].delegatedAmount = contractAddress.activeAmount(); validators[i].commissionRate = contractAddress.commissionRate_deprecated(); } else { validators[i].reward = validators[i].reward.add(INITIALIZED_AMOUNT); } validators[i].delegatorsReward = INITIALIZED_AMOUNT; } } function updateCheckpointRewardParams( uint256 _rewardDecreasePerCheckpoint, uint256 _maxRewardedCheckpoints, uint256 _checkpointRewardDelta ) external { require(_maxRewardedCheckpoints.mul(_rewardDecreasePerCheckpoint) <= CHK_REWARD_PRECISION); require(_checkpointRewardDelta <= CHK_REWARD_PRECISION); rewardDecreasePerCheckpoint = _rewardDecreasePerCheckpoint; maxRewardedCheckpoints = _maxRewardedCheckpoints; checkpointRewardDelta = _checkpointRewardDelta; _getOrCacheEventsHub().logRewardParams(_rewardDecreasePerCheckpoint, _maxRewardedCheckpoints, _checkpointRewardDelta); } function updateCommissionRate(uint256 validatorId, uint256 newCommissionRate) external { uint256 _epoch = currentEpoch; uint256 _lastCommissionUpdate = validators[validatorId].lastCommissionUpdate; require( // withdrawalDelay == dynasty (_lastCommissionUpdate.add(WITHDRAWAL_DELAY) <= _epoch) || _lastCommissionUpdate == 0, // For initial setting of commission rate "Cooldown" ); require(newCommissionRate <= MAX_COMMISION_RATE, "Incorrect value"); _getOrCacheEventsHub().logUpdateCommissionRate(validatorId, newCommissionRate, validators[validatorId].commissionRate); validators[validatorId].commissionRate = newCommissionRate; validators[validatorId].lastCommissionUpdate = _epoch; } function _getOrCacheEventsHub() private returns(EventsHub) { EventsHub _eventsHub = EventsHub(eventsHub); if (_eventsHub == EventsHub(0x0)) { _eventsHub = EventsHub(Registry(registry).contractMap(keccak256("eventsHub"))); eventsHub = address(_eventsHub); } return _eventsHub; } } // File: contracts/staking/stakeManager/StakeManager.sol pragma solidity 0.5.17; contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, DelegateProxyForwarder, StakeManagerStorageExtension { using SafeMath for uint256; using Merkle for bytes32; using RLPReader for bytes; using RLPReader for RLPReader.RLPItem; struct UnsignedValidatorsContext { uint256 unsignedValidatorIndex; uint256 validatorIndex; uint256[] unsignedValidators; address[] validators; uint256 totalValidators; } struct UnstakedValidatorsContext { uint256 deactivationEpoch; uint256[] deactivatedValidators; uint256 validatorIndex; } modifier onlyStaker(uint256 validatorId) { _assertStaker(validatorId); _; } function _assertStaker(uint256 validatorId) private view { require(NFTContract.ownerOf(validatorId) == msg.sender); } modifier onlyDelegation(uint256 validatorId) { _assertDelegation(validatorId); _; } function _assertDelegation(uint256 validatorId) private view { require(validators[validatorId].contractAddress == msg.sender, "Invalid contract address"); } constructor() public GovernanceLockable(address(0x0)) initializer {} function initialize( address _registry, address _rootchain, address _token, address _NFTContract, address _stakingLogger, address _validatorShareFactory, address _governance, address _owner, address _extensionCode ) external initializer { require(isContract(_extensionCode), "auction impl incorrect"); extensionCode = _extensionCode; governance = IGovernance(_governance); registry = _registry; rootChain = _rootchain; token = IERC20(_token); NFTContract = StakingNFT(_NFTContract); logger = StakingInfo(_stakingLogger); validatorShareFactory = ValidatorShareFactory(_validatorShareFactory); _transferOwnership(_owner); WITHDRAWAL_DELAY = (2**13); // unit: epoch currentEpoch = 1; dynasty = 886; // unit: epoch 50 days CHECKPOINT_REWARD = 20188 * (10**18); // update via governance minDeposit = (10**18); // in ERC20 token minHeimdallFee = (10**18); // in ERC20 token checkPointBlockInterval = 1024; signerUpdateLimit = 100; validatorThreshold = 7; //128 NFTCounter = 1; auctionPeriod = (2**13) / 4; // 1 week in epochs proposerBonus = 10; // 10 % of total rewards delegationEnabled = true; } function isOwner() public view returns (bool) { address _owner; bytes32 position = keccak256("matic.network.proxy.owner"); assembly { _owner := sload(position) } return msg.sender == _owner; } /** Public View Methods */ function getRegistry() public view returns (address) { return registry; } /** @dev Owner of validator slot NFT */ function ownerOf(uint256 tokenId) public view returns (address) { return NFTContract.ownerOf(tokenId); } function epoch() public view returns (uint256) { return currentEpoch; } function withdrawalDelay() public view returns (uint256) { return WITHDRAWAL_DELAY; } function validatorStake(uint256 validatorId) public view returns (uint256) { return validators[validatorId].amount; } function getValidatorId(address user) public view returns (uint256) { return NFTContract.tokenOfOwnerByIndex(user, 0); } function delegatedAmount(uint256 validatorId) public view returns (uint256) { return validators[validatorId].delegatedAmount; } function delegatorsReward(uint256 validatorId) public view returns (uint256) { (, uint256 _delegatorsReward) = _evaluateValidatorAndDelegationReward(validatorId); return validators[validatorId].delegatorsReward.add(_delegatorsReward).sub(INITIALIZED_AMOUNT); } function validatorReward(uint256 validatorId) public view returns (uint256) { uint256 _validatorReward; if (validators[validatorId].deactivationEpoch == 0) { (_validatorReward, ) = _evaluateValidatorAndDelegationReward(validatorId); } return validators[validatorId].reward.add(_validatorReward).sub(INITIALIZED_AMOUNT); } function currentValidatorSetSize() public view returns (uint256) { return validatorState.stakerCount; } function currentValidatorSetTotalStake() public view returns (uint256) { return validatorState.amount; } function getValidatorContract(uint256 validatorId) public view returns (address) { return validators[validatorId].contractAddress; } function isValidator(uint256 validatorId) public view returns (bool) { return _isValidator( validators[validatorId].status, validators[validatorId].amount, validators[validatorId].deactivationEpoch, currentEpoch ); } /** Governance Methods */ function setDelegationEnabled(bool enabled) public onlyGovernance { delegationEnabled = enabled; } // Housekeeping function. @todo remove later function forceUnstake(uint256 validatorId) external onlyGovernance { _unstake(validatorId, currentEpoch); } function setCurrentEpoch(uint256 _currentEpoch) external onlyGovernance { currentEpoch = _currentEpoch; } function setStakingToken(address _token) public onlyGovernance { require(_token != address(0x0)); token = IERC20(_token); } /** @dev Change the number of validators required to allow a passed header root */ function updateValidatorThreshold(uint256 newThreshold) public onlyGovernance { require(newThreshold != 0); logger.logThresholdChange(newThreshold, validatorThreshold); validatorThreshold = newThreshold; } function updateCheckPointBlockInterval(uint256 _blocks) public onlyGovernance { require(_blocks != 0); checkPointBlockInterval = _blocks; } function updateCheckpointReward(uint256 newReward) public onlyGovernance { require(newReward != 0); logger.logRewardUpdate(newReward, CHECKPOINT_REWARD); CHECKPOINT_REWARD = newReward; } function updateCheckpointRewardParams( uint256 _rewardDecreasePerCheckpoint, uint256 _maxRewardedCheckpoints, uint256 _checkpointRewardDelta ) public onlyGovernance { delegatedFwd( extensionCode, abi.encodeWithSelector( StakeManagerExtension(extensionCode).updateCheckpointRewardParams.selector, _rewardDecreasePerCheckpoint, _maxRewardedCheckpoints, _checkpointRewardDelta ) ); } // New implementation upgrade function migrateValidatorsData(uint256 validatorIdFrom, uint256 validatorIdTo) public onlyOwner { delegatedFwd( extensionCode, abi.encodeWithSelector( StakeManagerExtension(extensionCode).migrateValidatorsData.selector, validatorIdFrom, validatorIdTo ) ); } function insertSigners(address[] memory _signers) public onlyOwner { signers = _signers; } /** @dev Users must exit before this update or all funds may get lost */ function updateValidatorContractAddress(uint256 validatorId, address newContractAddress) public onlyGovernance { require(IValidatorShare(newContractAddress).owner() == address(this)); validators[validatorId].contractAddress = newContractAddress; } function updateDynastyValue(uint256 newDynasty) public onlyGovernance { require(newDynasty > 0); logger.logDynastyValueChange(newDynasty, dynasty); dynasty = newDynasty; WITHDRAWAL_DELAY = newDynasty; auctionPeriod = newDynasty.div(4); replacementCoolDown = currentEpoch.add(auctionPeriod); } // Housekeeping function. @todo remove later function stopAuctions(uint256 forNCheckpoints) public onlyGovernance { replacementCoolDown = currentEpoch.add(forNCheckpoints); } function updateProposerBonus(uint256 newProposerBonus) public onlyGovernance { logger.logProposerBonusChange(newProposerBonus, proposerBonus); require(newProposerBonus <= MAX_PROPOSER_BONUS, "too big"); proposerBonus = newProposerBonus; } function updateSignerUpdateLimit(uint256 _limit) public onlyGovernance { signerUpdateLimit = _limit; } function updateMinAmounts(uint256 _minDeposit, uint256 _minHeimdallFee) public onlyGovernance { minDeposit = _minDeposit; minHeimdallFee = _minHeimdallFee; } function drainValidatorShares( uint256 validatorId, address tokenAddr, address payable destination, uint256 amount ) external onlyGovernance { address contractAddr = validators[validatorId].contractAddress; require(contractAddr != address(0x0)); IValidatorShare(contractAddr).drain(tokenAddr, destination, amount); } function drain(address destination, uint256 amount) external onlyGovernance { _transferToken(destination, amount); } function reinitialize( address _NFTContract, address _stakingLogger, address _validatorShareFactory, address _extensionCode ) external onlyGovernance { require(isContract(_extensionCode)); eventsHub = address(0x0); extensionCode = _extensionCode; NFTContract = StakingNFT(_NFTContract); logger = StakingInfo(_stakingLogger); validatorShareFactory = ValidatorShareFactory(_validatorShareFactory); } /** Public Methods */ function topUpForFee(address user, uint256 heimdallFee) public onlyWhenUnlocked { _transferAndTopUp(user, msg.sender, heimdallFee, 0); } function claimFee( uint256 accumFeeAmount, uint256 index, bytes memory proof ) public { //Ignoring other params because rewards' distribution is on chain require( keccak256(abi.encode(msg.sender, accumFeeAmount)).checkMembership(index, accountStateRoot, proof), "Wrong acc proof" ); uint256 withdrawAmount = accumFeeAmount.sub(userFeeExit[msg.sender]); _claimFee(msg.sender, withdrawAmount); userFeeExit[msg.sender] = accumFeeAmount; _transferToken(msg.sender, withdrawAmount); } function totalStakedFor(address user) external view returns (uint256) { if (user == address(0x0) || NFTContract.balanceOf(user) == 0) { return 0; } return validators[NFTContract.tokenOfOwnerByIndex(user, 0)].amount; } function startAuction( uint256 validatorId, uint256 amount, bool _acceptDelegation, bytes calldata _signerPubkey ) external onlyWhenUnlocked { delegatedFwd( extensionCode, abi.encodeWithSelector( StakeManagerExtension(extensionCode).startAuction.selector, validatorId, amount, _acceptDelegation, _signerPubkey ) ); } function confirmAuctionBid( uint256 validatorId, uint256 heimdallFee /** for new validator */ ) external onlyWhenUnlocked { delegatedFwd( extensionCode, abi.encodeWithSelector( StakeManagerExtension(extensionCode).confirmAuctionBid.selector, validatorId, heimdallFee, address(this) ) ); } function dethroneAndStake( address auctionUser, uint256 heimdallFee, uint256 validatorId, uint256 auctionAmount, bool acceptDelegation, bytes calldata signerPubkey ) external { require(msg.sender == address(this), "not allowed"); // dethrone _transferAndTopUp(auctionUser, auctionUser, heimdallFee, 0); _unstake(validatorId, currentEpoch); uint256 newValidatorId = _stakeFor(auctionUser, auctionAmount, acceptDelegation, signerPubkey); logger.logConfirmAuction(newValidatorId, validatorId, auctionAmount); } function unstake(uint256 validatorId) external onlyStaker(validatorId) { require(validatorAuction[validatorId].amount == 0); Status status = validators[validatorId].status; require( validators[validatorId].activationEpoch > 0 && validators[validatorId].deactivationEpoch == 0 && (status == Status.Active || status == Status.Locked) ); uint256 exitEpoch = currentEpoch.add(1); // notice period _unstake(validatorId, exitEpoch); } function transferFunds( uint256 validatorId, uint256 amount, address delegator ) external returns (bool) { require( validators[validatorId].contractAddress == msg.sender || Registry(registry).getSlashingManagerAddress() == msg.sender, "not allowed" ); return token.transfer(delegator, amount); } function delegationDeposit( uint256 validatorId, uint256 amount, address delegator ) external onlyDelegation(validatorId) returns (bool) { return token.transferFrom(delegator, address(this), amount); } function stakeFor( address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey ) public onlyWhenUnlocked { require(currentValidatorSetSize() < validatorThreshold, "no more slots"); require(amount >= minDeposit, "not enough deposit"); _transferAndTopUp(user, msg.sender, heimdallFee, amount); _stakeFor(user, amount, acceptDelegation, signerPubkey); } function unstakeClaim(uint256 validatorId) public onlyStaker(validatorId) { uint256 deactivationEpoch = validators[validatorId].deactivationEpoch; // can only claim stake back after WITHDRAWAL_DELAY require( deactivationEpoch > 0 && deactivationEpoch.add(WITHDRAWAL_DELAY) <= currentEpoch && validators[validatorId].status != Status.Unstaked ); uint256 amount = validators[validatorId].amount; uint256 newTotalStaked = totalStaked.sub(amount); totalStaked = newTotalStaked; // claim last checkpoint reward if it was signed by validator _liquidateRewards(validatorId, msg.sender); NFTContract.burn(validatorId); validators[validatorId].amount = 0; validators[validatorId].jailTime = 0; validators[validatorId].signer = address(0); signerToValidator[validators[validatorId].signer] = INCORRECT_VALIDATOR_ID; validators[validatorId].status = Status.Unstaked; _transferToken(msg.sender, amount); logger.logUnstaked(msg.sender, validatorId, amount, newTotalStaked); } function restake( uint256 validatorId, uint256 amount, bool stakeRewards ) public onlyWhenUnlocked onlyStaker(validatorId) { require(validators[validatorId].deactivationEpoch == 0, "No restaking"); if (amount > 0) { _transferTokenFrom(msg.sender, address(this), amount); } _updateRewards(validatorId); if (stakeRewards) { amount = amount.add(validators[validatorId].reward).sub(INITIALIZED_AMOUNT); validators[validatorId].reward = INITIALIZED_AMOUNT; } uint256 newTotalStaked = totalStaked.add(amount); totalStaked = newTotalStaked; validators[validatorId].amount = validators[validatorId].amount.add(amount); updateTimeline(int256(amount), 0, 0); logger.logStakeUpdate(validatorId); logger.logRestaked(validatorId, validators[validatorId].amount, newTotalStaked); } function withdrawRewards(uint256 validatorId) public onlyStaker(validatorId) { _updateRewards(validatorId); _liquidateRewards(validatorId, msg.sender); } function migrateDelegation( uint256 fromValidatorId, uint256 toValidatorId, uint256 amount ) public { // allow to move to any non-foundation node require(toValidatorId > 7, "Invalid migration"); IValidatorShare(validators[fromValidatorId].contractAddress).migrateOut(msg.sender, amount); IValidatorShare(validators[toValidatorId].contractAddress).migrateIn(msg.sender, amount); } function updateValidatorState(uint256 validatorId, int256 amount) public onlyDelegation(validatorId) { if (amount > 0) { // deposit during shares purchase require(delegationEnabled, "Delegation is disabled"); } uint256 deactivationEpoch = validators[validatorId].deactivationEpoch; if (deactivationEpoch == 0) { // modify timeline only if validator didn't unstake updateTimeline(amount, 0, 0); } else if (deactivationEpoch > currentEpoch) { // validator just unstaked, need to wait till next checkpoint revert("unstaking"); } if (amount >= 0) { increaseValidatorDelegatedAmount(validatorId, uint256(amount)); } else { decreaseValidatorDelegatedAmount(validatorId, uint256(amount * -1)); } } function increaseValidatorDelegatedAmount(uint256 validatorId, uint256 amount) private { validators[validatorId].delegatedAmount = validators[validatorId].delegatedAmount.add(amount); } function decreaseValidatorDelegatedAmount(uint256 validatorId, uint256 amount) public onlyDelegation(validatorId) { validators[validatorId].delegatedAmount = validators[validatorId].delegatedAmount.sub(amount); } function updateSigner(uint256 validatorId, bytes memory signerPubkey) public onlyStaker(validatorId) { address signer = _getAndAssertSigner(signerPubkey); uint256 _currentEpoch = currentEpoch; require(_currentEpoch >= latestSignerUpdateEpoch[validatorId].add(signerUpdateLimit), "Not allowed"); address currentSigner = validators[validatorId].signer; // update signer event logger.logSignerChange(validatorId, currentSigner, signer, signerPubkey); if (validators[validatorId].deactivationEpoch == 0) { // didn't unstake, swap signer in the list _removeSigner(currentSigner); _insertSigner(signer); } signerToValidator[currentSigner] = INCORRECT_VALIDATOR_ID; signerToValidator[signer] = validatorId; validators[validatorId].signer = signer; // reset update time to current time latestSignerUpdateEpoch[validatorId] = _currentEpoch; } function checkSignatures( uint256 blockInterval, bytes32 voteHash, bytes32 stateRoot, address proposer, uint256[3][] calldata sigs ) external onlyRootChain returns (uint256) { uint256 _currentEpoch = currentEpoch; uint256 signedStakePower; address lastAdd; uint256 totalStakers = validatorState.stakerCount; UnsignedValidatorsContext memory unsignedCtx; unsignedCtx.unsignedValidators = new uint256[](signers.length + totalStakers); unsignedCtx.validators = signers; unsignedCtx.validatorIndex = 0; unsignedCtx.totalValidators = signers.length; UnstakedValidatorsContext memory unstakeCtx; unstakeCtx.deactivatedValidators = new uint256[](signers.length + totalStakers); for (uint256 i = 0; i < sigs.length; ++i) { address signer = ECVerify.ecrecovery(voteHash, sigs[i]); if (signer == lastAdd) { // if signer signs twice, just skip this signature continue; } if (signer < lastAdd) { // if signatures are out of order - break out, it is not possible to keep track of unsigned validators break; } uint256 validatorId = signerToValidator[signer]; uint256 amount = validators[validatorId].amount; Status status = validators[validatorId].status; unstakeCtx.deactivationEpoch = validators[validatorId].deactivationEpoch; if (_isValidator(status, amount, unstakeCtx.deactivationEpoch, _currentEpoch)) { lastAdd = signer; signedStakePower = signedStakePower.add(validators[validatorId].delegatedAmount).add(amount); if (unstakeCtx.deactivationEpoch != 0) { // this validator not a part of signers list anymore unstakeCtx.deactivatedValidators[unstakeCtx.validatorIndex] = validatorId; unstakeCtx.validatorIndex++; } else { unsignedCtx = _fillUnsignedValidators(unsignedCtx, signer); } } else if (status == Status.Locked) { // TODO fix double unsignedValidators appearance // make sure that jailed validator doesn't get his rewards too unsignedCtx.unsignedValidators[unsignedCtx.unsignedValidatorIndex] = validatorId; unsignedCtx.unsignedValidatorIndex++; unsignedCtx.validatorIndex++; } } // find the rest of validators without signature unsignedCtx = _fillUnsignedValidators(unsignedCtx, address(0)); return _increaseRewardAndAssertConsensus( blockInterval, proposer, signedStakePower, stateRoot, unsignedCtx.unsignedValidators, unsignedCtx.unsignedValidatorIndex, unstakeCtx.deactivatedValidators, unstakeCtx.validatorIndex ); } function updateCommissionRate(uint256 validatorId, uint256 newCommissionRate) external onlyStaker(validatorId) { _updateRewards(validatorId); delegatedFwd( extensionCode, abi.encodeWithSelector( StakeManagerExtension(extensionCode).updateCommissionRate.selector, validatorId, newCommissionRate ) ); } function withdrawDelegatorsReward(uint256 validatorId) public onlyDelegation(validatorId) returns (uint256) { _updateRewards(validatorId); uint256 totalReward = validators[validatorId].delegatorsReward.sub(INITIALIZED_AMOUNT); validators[validatorId].delegatorsReward = INITIALIZED_AMOUNT; return totalReward; } function slash(bytes calldata _slashingInfoList) external returns (uint256) { require(Registry(registry).getSlashingManagerAddress() == msg.sender, "Not slash manager"); RLPReader.RLPItem[] memory slashingInfoList = _slashingInfoList.toRlpItem().toList(); int256 valJailed; uint256 jailedAmount; uint256 totalAmount; uint256 i; for (; i < slashingInfoList.length; i++) { RLPReader.RLPItem[] memory slashData = slashingInfoList[i].toList(); uint256 validatorId = slashData[0].toUint(); _updateRewards(validatorId); uint256 _amount = slashData[1].toUint(); totalAmount = totalAmount.add(_amount); address delegationContract = validators[validatorId].contractAddress; if (delegationContract != address(0x0)) { uint256 delSlashedAmount = IValidatorShare(delegationContract).slash( validators[validatorId].amount, validators[validatorId].delegatedAmount, _amount ); _amount = _amount.sub(delSlashedAmount); } uint256 validatorStakeSlashed = validators[validatorId].amount.sub(_amount); validators[validatorId].amount = validatorStakeSlashed; if (validatorStakeSlashed == 0) { _unstake(validatorId, currentEpoch); } else if (slashData[2].toBoolean()) { jailedAmount = jailedAmount.add(_jail(validatorId, 1)); valJailed++; } } //update timeline updateTimeline(-int256(totalAmount.add(jailedAmount)), -valJailed, 0); return totalAmount; } function unjail(uint256 validatorId) public onlyStaker(validatorId) { require(validators[validatorId].status == Status.Locked, "Not jailed"); require(validators[validatorId].deactivationEpoch == 0, "Already unstaking"); uint256 _currentEpoch = currentEpoch; require(validators[validatorId].jailTime <= _currentEpoch, "Incomplete jail period"); uint256 amount = validators[validatorId].amount; require(amount >= minDeposit); address delegationContract = validators[validatorId].contractAddress; if (delegationContract != address(0x0)) { IValidatorShare(delegationContract).unlock(); } // undo timeline so that validator is normal validator updateTimeline(int256(amount.add(validators[validatorId].delegatedAmount)), 1, 0); validators[validatorId].status = Status.Active; address signer = validators[validatorId].signer; logger.logUnjailed(validatorId, signer); } function updateTimeline( int256 amount, int256 stakerCount, uint256 targetEpoch ) internal { if (targetEpoch == 0) { // update total stake and validator count if (amount > 0) { validatorState.amount = validatorState.amount.add(uint256(amount)); } else if (amount < 0) { validatorState.amount = validatorState.amount.sub(uint256(amount * -1)); } if (stakerCount > 0) { validatorState.stakerCount = validatorState.stakerCount.add(uint256(stakerCount)); } else if (stakerCount < 0) { validatorState.stakerCount = validatorState.stakerCount.sub(uint256(stakerCount * -1)); } } else { validatorStateChanges[targetEpoch].amount += amount; validatorStateChanges[targetEpoch].stakerCount += stakerCount; } } function updateValidatorDelegation(bool delegation) external { uint256 validatorId = signerToValidator[msg.sender]; require( _isValidator( validators[validatorId].status, validators[validatorId].amount, validators[validatorId].deactivationEpoch, currentEpoch ), "not validator" ); address contractAddr = validators[validatorId].contractAddress; require(contractAddr != address(0x0), "Delegation is disabled"); IValidatorShare(contractAddr).updateDelegation(delegation); } /** Private Methods */ function _getAndAssertSigner(bytes memory pub) private view returns (address) { require(pub.length == 64, "not pub"); address signer = address(uint160(uint256(keccak256(pub)))); require(signer != address(0) && signerToValidator[signer] == 0, "Invalid signer"); return signer; } function _isValidator( Status status, uint256 amount, uint256 deactivationEpoch, uint256 _currentEpoch ) private pure returns (bool) { return (amount > 0 && (deactivationEpoch == 0 || deactivationEpoch > _currentEpoch) && status == Status.Active); } function _fillUnsignedValidators(UnsignedValidatorsContext memory context, address signer) private view returns(UnsignedValidatorsContext memory) { while (context.validatorIndex < context.totalValidators && context.validators[context.validatorIndex] != signer) { context.unsignedValidators[context.unsignedValidatorIndex] = signerToValidator[context.validators[context.validatorIndex]]; context.unsignedValidatorIndex++; context.validatorIndex++; } context.validatorIndex++; return context; } function _calculateCheckpointReward( uint256 blockInterval, uint256 signedStakePower, uint256 currentTotalStake ) internal returns (uint256) { // checkpoint rewards are based on BlockInterval multiplied on `CHECKPOINT_REWARD` // for bigger checkpoints reward is reduced by rewardDecreasePerCheckpoint for each subsequent interval // for smaller checkpoints // if interval is 50% of checkPointBlockInterval then reward R is half of `CHECKPOINT_REWARD` // and then stakePower is 90% of currentValidatorSetTotalStake then final reward is 90% of R uint256 targetBlockInterval = checkPointBlockInterval; uint256 ckpReward = CHECKPOINT_REWARD; uint256 fullIntervals = Math.min(blockInterval / targetBlockInterval, maxRewardedCheckpoints); // only apply to full checkpoints if (fullIntervals > 0 && fullIntervals != prevBlockInterval) { if (prevBlockInterval != 0) { // give more reward for faster and less for slower checkpoint uint256 delta = (ckpReward * checkpointRewardDelta / CHK_REWARD_PRECISION); if (prevBlockInterval > fullIntervals) { // checkpoint is faster ckpReward += delta; } else { ckpReward -= delta; } } prevBlockInterval = fullIntervals; } uint256 reward; if (blockInterval > targetBlockInterval) { // count how many full intervals uint256 _rewardDecreasePerCheckpoint = rewardDecreasePerCheckpoint; // calculate reward for full intervals reward = ckpReward.mul(fullIntervals).sub(ckpReward.mul(((fullIntervals - 1) * fullIntervals / 2).mul(_rewardDecreasePerCheckpoint)).div(CHK_REWARD_PRECISION)); // adjust block interval, in case last interval is not full blockInterval = blockInterval.sub(fullIntervals.mul(targetBlockInterval)); // adjust checkpoint reward by the amount it suppose to decrease ckpReward = ckpReward.sub(ckpReward.mul(fullIntervals).mul(_rewardDecreasePerCheckpoint).div(CHK_REWARD_PRECISION)); } // give proportionally less for the rest reward = reward.add(blockInterval.mul(ckpReward).div(targetBlockInterval)); reward = reward.mul(signedStakePower).div(currentTotalStake); return reward; } function _increaseRewardAndAssertConsensus( uint256 blockInterval, address proposer, uint256 signedStakePower, bytes32 stateRoot, uint256[] memory unsignedValidators, uint256 totalUnsignedValidators, uint256[] memory deactivatedValidators, uint256 totalDeactivatedValidators ) private returns (uint256) { uint256 currentTotalStake = validatorState.amount; require(signedStakePower >= currentTotalStake.mul(2).div(3).add(1), "2/3+1 non-majority!"); uint256 reward = _calculateCheckpointReward(blockInterval, signedStakePower, currentTotalStake); uint256 _proposerBonus = reward.mul(proposerBonus).div(MAX_PROPOSER_BONUS); uint256 proposerId = signerToValidator[proposer]; Validator storage _proposer = validators[proposerId]; _proposer.reward = _proposer.reward.add(_proposerBonus); // update stateMerkleTree root for accounts balance on heimdall chain accountStateRoot = stateRoot; uint256 newRewardPerStake = rewardPerStake.add(reward.sub(_proposerBonus).mul(REWARD_PRECISION).div(signedStakePower)); // evaluate rewards for validator who did't sign and set latest reward per stake to new value to avoid them from getting new rewards. _updateValidatorsRewards(unsignedValidators, totalUnsignedValidators, newRewardPerStake); // distribute rewards between signed validators rewardPerStake = newRewardPerStake; // evaluate rewards for unstaked validators to avoid getting new rewards until they claim their stake _updateValidatorsRewards(deactivatedValidators, totalDeactivatedValidators, newRewardPerStake); _finalizeCommit(); return reward; } function _updateValidatorsRewards( uint256[] memory unsignedValidators, uint256 totalUnsignedValidators, uint256 newRewardPerStake ) private { uint256 currentRewardPerStake = rewardPerStake; for (uint256 i = 0; i < totalUnsignedValidators; ++i) { _updateRewardsAndCommit(unsignedValidators[i], currentRewardPerStake, newRewardPerStake); } } function _updateRewardsAndCommit( uint256 validatorId, uint256 currentRewardPerStake, uint256 newRewardPerStake ) private { uint256 initialRewardPerStake = validators[validatorId].initialRewardPerStake; // attempt to save gas in case if rewards were updated previosuly if (initialRewardPerStake < currentRewardPerStake) { uint256 validatorsStake = validators[validatorId].amount; uint256 delegatedAmount = validators[validatorId].delegatedAmount; if (delegatedAmount > 0) { uint256 combinedStakePower = validatorsStake.add(delegatedAmount); _increaseValidatorRewardWithDelegation( validatorId, validatorsStake, delegatedAmount, _getEligibleValidatorReward( validatorId, combinedStakePower, currentRewardPerStake, initialRewardPerStake ) ); } else { _increaseValidatorReward( validatorId, _getEligibleValidatorReward( validatorId, validatorsStake, currentRewardPerStake, initialRewardPerStake ) ); } } if (newRewardPerStake > initialRewardPerStake) { validators[validatorId].initialRewardPerStake = newRewardPerStake; } } function _updateRewards(uint256 validatorId) private { _updateRewardsAndCommit(validatorId, rewardPerStake, rewardPerStake); } function _getEligibleValidatorReward( uint256 validatorId, uint256 validatorStakePower, uint256 currentRewardPerStake, uint256 initialRewardPerStake ) private pure returns (uint256) { uint256 eligibleReward = currentRewardPerStake - initialRewardPerStake; return eligibleReward.mul(validatorStakePower).div(REWARD_PRECISION); } function _increaseValidatorReward(uint256 validatorId, uint256 reward) private { if (reward > 0) { validators[validatorId].reward = validators[validatorId].reward.add(reward); } } function _increaseValidatorRewardWithDelegation( uint256 validatorId, uint256 validatorsStake, uint256 delegatedAmount, uint256 reward ) private { uint256 combinedStakePower = delegatedAmount.add(validatorsStake); (uint256 validatorReward, uint256 delegatorsReward) = _getValidatorAndDelegationReward(validatorId, validatorsStake, reward, combinedStakePower); if (delegatorsReward > 0) { validators[validatorId].delegatorsReward = validators[validatorId].delegatorsReward.add(delegatorsReward); } if (validatorReward > 0) { validators[validatorId].reward = validators[validatorId].reward.add(validatorReward); } } function _getValidatorAndDelegationReward( uint256 validatorId, uint256 validatorsStake, uint256 reward, uint256 combinedStakePower ) internal view returns (uint256, uint256) { if (combinedStakePower == 0) { return (0, 0); } uint256 validatorReward = validatorsStake.mul(reward).div(combinedStakePower); // add validator commission from delegation reward uint256 commissionRate = validators[validatorId].commissionRate; if (commissionRate > 0) { validatorReward = validatorReward.add( reward.sub(validatorReward).mul(commissionRate).div(MAX_COMMISION_RATE) ); } uint256 delegatorsReward = reward.sub(validatorReward); return (validatorReward, delegatorsReward); } function _evaluateValidatorAndDelegationReward(uint256 validatorId) private view returns (uint256 validatorReward, uint256 delegatorsReward) { uint256 validatorsStake = validators[validatorId].amount; uint256 combinedStakePower = validatorsStake.add(validators[validatorId].delegatedAmount); uint256 eligibleReward = rewardPerStake - validators[validatorId].initialRewardPerStake; return _getValidatorAndDelegationReward( validatorId, validatorsStake, eligibleReward.mul(combinedStakePower).div(REWARD_PRECISION), combinedStakePower ); } function _jail(uint256 validatorId, uint256 jailCheckpoints) internal returns (uint256) { address delegationContract = validators[validatorId].contractAddress; if (delegationContract != address(0x0)) { IValidatorShare(delegationContract).lock(); } uint256 _currentEpoch = currentEpoch; validators[validatorId].jailTime = _currentEpoch.add(jailCheckpoints); validators[validatorId].status = Status.Locked; logger.logJailed(validatorId, _currentEpoch, validators[validatorId].signer); return validators[validatorId].amount.add(validators[validatorId].delegatedAmount); } function _stakeFor( address user, uint256 amount, bool acceptDelegation, bytes memory signerPubkey ) internal returns (uint256) { address signer = _getAndAssertSigner(signerPubkey); uint256 _currentEpoch = currentEpoch; uint256 validatorId = NFTCounter; StakingInfo _logger = logger; uint256 newTotalStaked = totalStaked.add(amount); totalStaked = newTotalStaked; validators[validatorId] = Validator({ reward: INITIALIZED_AMOUNT, amount: amount, activationEpoch: _currentEpoch, deactivationEpoch: 0, jailTime: 0, signer: signer, contractAddress: acceptDelegation ? validatorShareFactory.create(validatorId, address(_logger), registry) : address(0x0), status: Status.Active, commissionRate: 0, lastCommissionUpdate: 0, delegatorsReward: INITIALIZED_AMOUNT, delegatedAmount: 0, initialRewardPerStake: rewardPerStake }); latestSignerUpdateEpoch[validatorId] = _currentEpoch; NFTContract.mint(user, validatorId); signerToValidator[signer] = validatorId; updateTimeline(int256(amount), 1, 0); // no Auctions for 1 dynasty validatorAuction[validatorId].startEpoch = _currentEpoch; _logger.logStaked(signer, signerPubkey, validatorId, _currentEpoch, amount, newTotalStaked); NFTCounter = validatorId.add(1); _insertSigner(signer); return validatorId; } function _unstake(uint256 validatorId, uint256 exitEpoch) internal { // TODO: if validators unstake and slashed to 0, he will be forced to unstake again // must think how to handle it correctly _updateRewards(validatorId); uint256 amount = validators[validatorId].amount; address validator = ownerOf(validatorId); validators[validatorId].deactivationEpoch = exitEpoch; // unbond all delegators in future int256 delegationAmount = int256(validators[validatorId].delegatedAmount); address delegationContract = validators[validatorId].contractAddress; if (delegationContract != address(0)) { IValidatorShare(delegationContract).lock(); } _removeSigner(validators[validatorId].signer); _liquidateRewards(validatorId, validator); uint256 targetEpoch = exitEpoch <= currentEpoch ? 0 : exitEpoch; updateTimeline(-(int256(amount) + delegationAmount), -1, targetEpoch); logger.logUnstakeInit(validator, validatorId, exitEpoch, amount); } function _finalizeCommit() internal { uint256 _currentEpoch = currentEpoch; uint256 nextEpoch = _currentEpoch.add(1); StateChange memory changes = validatorStateChanges[nextEpoch]; updateTimeline(changes.amount, changes.stakerCount, 0); delete validatorStateChanges[_currentEpoch]; currentEpoch = nextEpoch; } function _liquidateRewards(uint256 validatorId, address validatorUser) private { uint256 reward = validators[validatorId].reward.sub(INITIALIZED_AMOUNT); totalRewardsLiquidated = totalRewardsLiquidated.add(reward); validators[validatorId].reward = INITIALIZED_AMOUNT; validators[validatorId].initialRewardPerStake = rewardPerStake; _transferToken(validatorUser, reward); logger.logClaimRewards(validatorId, reward, totalRewardsLiquidated); } function _transferToken(address destination, uint256 amount) private { require(token.transfer(destination, amount), "transfer failed"); } function _transferTokenFrom( address from, address destination, uint256 amount ) private { require(token.transferFrom(from, destination, amount), "transfer from failed"); } function _transferAndTopUp( address user, address from, uint256 fee, uint256 additionalAmount ) private { require(fee >= minHeimdallFee, "fee too small"); _transferTokenFrom(from, address(this), fee.add(additionalAmount)); totalHeimdallFee = totalHeimdallFee.add(fee); logger.logTopUpFee(user, fee); } function _claimFee(address user, uint256 amount) private { totalHeimdallFee = totalHeimdallFee.sub(amount); logger.logClaimFee(user, amount); } function _insertSigner(address newSigner) internal { signers.push(newSigner); uint lastIndex = signers.length - 1; uint i = lastIndex; for (; i > 0; --i) { address signer = signers[i - 1]; if (signer < newSigner) { break; } signers[i] = signer; } if (i != lastIndex) { signers[i] = newSigner; } } function _removeSigner(address signerToDelete) internal { uint256 totalSigners = signers.length; address swapSigner = signers[totalSigners - 1]; delete signers[totalSigners - 1]; // bubble last element to the beginning until target signer is met for (uint256 i = totalSigners - 1; i > 0; --i) { if (swapSigner == signerToDelete) { break; } (swapSigner, signers[i - 1]) = (signers[i - 1], swapSigner); } signers.length = totalSigners - 1; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousRootChain","type":"address"},{"indexed":true,"internalType":"address","name":"newRootChain","type":"address"}],"name":"RootChainChanged","type":"event"},{"constant":true,"inputs":[],"name":"CHECKPOINT_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"NFTContract","outputs":[{"internalType":"contract StakingNFT","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"NFTCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"WITHDRAWAL_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"accountStateRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"auctionPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newRootChain","type":"address"}],"name":"changeRootChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"checkPointBlockInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"blockInterval","type":"uint256"},{"internalType":"bytes32","name":"voteHash","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"address","name":"proposer","type":"address"},{"internalType":"uint256[3][]","name":"sigs","type":"uint256[3][]"}],"name":"checkSignatures","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"checkpointRewardDelta","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"accumFeeAmount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"claimFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"},{"internalType":"uint256","name":"heimdallFee","type":"uint256"}],"name":"confirmAuctionBid","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"currentEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentValidatorSetSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentValidatorSetTotalStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"decreaseValidatorDelegatedAmount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"}],"name":"delegatedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"delegator","type":"address"}],"name":"delegationDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"delegationEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"}],"name":"delegatorsReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"auctionUser","type":"address"},{"internalType":"uint256","name":"heimdallFee","type":"uint256"},{"internalType":"uint256","name":"validatorId","type":"uint256"},{"internalType":"uint256","name":"auctionAmount","type":"uint256"},{"internalType":"bool","name":"acceptDelegation","type":"bool"},{"internalType":"bytes","name":"signerPubkey","type":"bytes"}],"name":"dethroneAndStake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"drain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"},{"internalType":"address","name":"tokenAddr","type":"address"},{"internalType":"address payable","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"drainValidatorShares","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"dynasty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"eventsHub","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"extensionCode","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"}],"name":"forceUnstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"}],"name":"getValidatorContract","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getValidatorId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"governance","outputs":[{"internalType":"contract IGovernance","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_registry","type":"address"},{"internalType":"address","name":"_rootchain","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_NFTContract","type":"address"},{"internalType":"address","name":"_stakingLogger","type":"address"},{"internalType":"address","name":"_validatorShareFactory","type":"address"},{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_extensionCode","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"_signers","type":"address[]"}],"name":"insertSigners","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"}],"name":"isValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"latestSignerUpdateEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"lock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"locked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"logger","outputs":[{"internalType":"contract StakingInfo","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxRewardedCheckpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"fromValidatorId","type":"uint256"},{"internalType":"uint256","name":"toValidatorId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"migrateDelegation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorIdFrom","type":"uint256"},{"internalType":"uint256","name":"validatorIdTo","type":"uint256"}],"name":"migrateValidatorsData","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"minDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minHeimdallFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"prevBlockInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"proposerBonus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"registry","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_NFTContract","type":"address"},{"internalType":"address","name":"_stakingLogger","type":"address"},{"internalType":"address","name":"_validatorShareFactory","type":"address"},{"internalType":"address","name":"_extensionCode","type":"address"}],"name":"reinitialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"replacementCoolDown","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"stakeRewards","type":"bool"}],"name":"restake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rewardDecreasePerCheckpoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rewardPerStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rootChain","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_currentEpoch","type":"uint256"}],"name":"setCurrentEpoch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setDelegationEnabled","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"setStakingToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"signerToValidator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"signerUpdateLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"signers","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"_slashingInfoList","type":"bytes"}],"name":"slash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"heimdallFee","type":"uint256"},{"internalType":"bool","name":"acceptDelegation","type":"bool"},{"internalType":"bytes","name":"signerPubkey","type":"bytes"}],"name":"stakeFor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"_acceptDelegation","type":"bool"},{"internalType":"bytes","name":"_signerPubkey","type":"bytes"}],"name":"startAuction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"forNCheckpoints","type":"uint256"}],"name":"stopAuctions","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"heimdallFee","type":"uint256"}],"name":"topUpForFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalHeimdallFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalRewardsLiquidated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"totalStakedFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"delegator","type":"address"}],"name":"transferFunds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"}],"name":"unjail","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"}],"name":"unstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"}],"name":"unstakeClaim","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_blocks","type":"uint256"}],"name":"updateCheckPointBlockInterval","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newReward","type":"uint256"}],"name":"updateCheckpointReward","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_rewardDecreasePerCheckpoint","type":"uint256"},{"internalType":"uint256","name":"_maxRewardedCheckpoints","type":"uint256"},{"internalType":"uint256","name":"_checkpointRewardDelta","type":"uint256"}],"name":"updateCheckpointRewardParams","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"},{"internalType":"uint256","name":"newCommissionRate","type":"uint256"}],"name":"updateCommissionRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newDynasty","type":"uint256"}],"name":"updateDynastyValue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_minDeposit","type":"uint256"},{"internalType":"uint256","name":"_minHeimdallFee","type":"uint256"}],"name":"updateMinAmounts","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newProposerBonus","type":"uint256"}],"name":"updateProposerBonus","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"},{"internalType":"bytes","name":"signerPubkey","type":"bytes"}],"name":"updateSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"updateSignerUpdateLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"},{"internalType":"address","name":"newContractAddress","type":"address"}],"name":"updateValidatorContractAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"delegation","type":"bool"}],"name":"updateValidatorDelegation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"},{"internalType":"int256","name":"amount","type":"int256"}],"name":"updateValidatorState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newThreshold","type":"uint256"}],"name":"updateValidatorThreshold","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userFeeExit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"validatorAuction","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"startEpoch","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"acceptDelegation","type":"bool"},{"internalType":"bytes","name":"signerPubkey","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"}],"name":"validatorReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"validatorShareFactory","outputs":[{"internalType":"contract ValidatorShareFactory","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"}],"name":"validatorStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"validatorState","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"stakerCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"validatorStateChanges","outputs":[{"internalType":"int256","name":"amount","type":"int256"},{"internalType":"int256","name":"stakerCount","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"validatorThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"validators","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"activationEpoch","type":"uint256"},{"internalType":"uint256","name":"deactivationEpoch","type":"uint256"},{"internalType":"uint256","name":"jailTime","type":"uint256"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"enum StakeManagerStorage.Status","name":"status","type":"uint8"},{"internalType":"uint256","name":"commissionRate","type":"uint256"},{"internalType":"uint256","name":"lastCommissionUpdate","type":"uint256"},{"internalType":"uint256","name":"delegatorsReward","type":"uint256"},{"internalType":"uint256","name":"delegatedAmount","type":"uint256"},{"internalType":"uint256","name":"initialRewardPerStake","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"}],"name":"withdrawDelegatorsReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorId","type":"uint256"}],"name":"withdrawRewards","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"withdrawalDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040526023805460ff191690553480156200001b57600080fd5b5060008054610100600160a81b0319168155600180546001600160a01b0319163317908190556040516001600160a01b039190911691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a360235460ff1615620000ea57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f616c726561647920696e69746564000000000000000000000000000000000000604482015290519081900360640190fd5b6023805460ff19166001179055615e2880620001076000396000f3fe608060405234801561001057600080fd5b50600436106106235760003560e01c80637d66975211610336578063b1d23f02116101c3578063e6692f491161010f578063f5e95acb116100ad578063f8a3176c11610087578063f8a3176c14611522578063fb1ef52c1461152a578063fba58f3414611553578063fc0c546a1461155b57610623565b8063f5e95acb14611493578063f771fc87146114fd578063f83d08ba1461151a57610623565b8063f24ccbfe116100e9578063f24ccbfe1461139b578063f28699fa146113a3578063f2fde38b146113c2578063f41a9642146113e857610623565b8063e6692f491461133b578063e8afa8e814611358578063eceec1d31461137e57610623565b8063cf3090121161017c578063d86d53e711610156578063d86d53e7146112eb578063dcd962b214611308578063e568959a1461132b578063e59ee0c61461133357610623565b8063cf309012146112a7578063d6de07d0146112af578063d7f5549d146112ce57610623565b8063b1d23f02146111e4578063b65de35e14611207578063bc8756a914611224578063c710e92214611256578063cbf383d514611282578063cd6b83881461129f57610623565b8063987ab9db11610282578063a440ab1e1161023b578063a69df4b511610215578063a69df4b5146111a0578063a7ab6961146111a8578063a8dc889b146111b0578063b184be81146111b857610623565b8063a440ab1e146110f8578063a476907114611115578063a68548771461111d57610623565b8063987ab9db1461106257806399d18f6f1461106a5780639a8a62431461108d5780639b33f434146110955780639ddbbf85146110b25780639ff11500146110d557610623565b8063883b455f116102ef578063900cf0cf116102c9578063900cf0cf14611018578063914601491461102057806391f1a3a51461103d5780639342c8f41461104557610623565b8063883b455f146110005780638da5cb5b146110085780638f32d59b1461101057610623565b80637d66975214610f8b5780637ed4b27c14610f935780637f4b432314610fb05780637f952d9514610fcd578063817b1cd214610fd5578063858a7c0314610fdd57610623565b8063451b5985116104b45780635e47655f116104005780637060054d116103b957806377939d101161039357806377939d1014610f4d57806378f84a4414610f555780637b10399914610f7b5780637c7eaf1a14610f8357610623565b80637060054d14610f35578063715018a614610f3d5780637667180814610f4557610623565b80635e47655f14610d7357806360c8d12214610de15780636352211e14610e0a5780636365679814610e2757806368cb812a14610e535780636901b25314610f0357610623565b806352b8115d1161046d5780635508d8e1116104475780635508d8e114610d3e57806356342d8c14610d465780635aa6e67514610d635780635ab1bd5314610d6b57610623565b806352b8115d14610bd75780635325e14414610c6f57806354b8c60114610d3657610623565b8063451b598514610a9657806348ab8b2a14610a9e5780634b341aed14610ada5780634e3c83f114610b005780634fd101d714610b085780634fdd20f114610b1057610623565b806325316411116105735780632fa9d18b1161052c57806335aa2e441161050657806335aa2e44146109925780633862da0b14610a4b57806339610f7814610a7157806341b3d18514610a8e57610623565b80632fa9d18b146108f357806331c2273b14610982578063342745861461098a57610623565b8063253164111461079b57806325726df2146107a35780632649263a146107d957806328cc4e411461080a5780632cf44a43146108355780632e17de78146108d657610623565b8063174e6832116105e05780631ae4818f116105ba5780631ae4818f146107175780631dd6b9b11461073b5780631e9b12ef146107585780632079fb9a1461077e57610623565b8063174e6832146106cc578063178c2c83146106f257806317c2b9101461070f57610623565b806306cfb10414610628578063078a13b1146106475780630cccfc58146106855780630e15561a1461069f5780630ebb172a146106a757806316827b1b146106af575b600080fd5b6106456004803603602081101561063e57600080fd5b5035611563565b005b6106456004803603608081101561065d57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060013516611570565b61068d6115e8565b60408051918252519081900360200190f35b61068d6115ee565b61068d6115f4565b610645600480360360208110156106c557600080fd5b50356115fa565b61068d600480360360208110156106e257600080fd5b50356001600160a01b0316611683565b6106456004803603602081101561070857600080fd5b503561170d565b61068d61199a565b61071f6119a0565b604080516001600160a01b039092168252519081900360200190f35b6106456004803603602081101561075157600080fd5b50356119af565b6106456004803603602081101561076e57600080fd5b50356001600160a01b03166119bc565b61071f6004803603602081101561079457600080fd5b50356119f9565b61068d611a20565b6107c0600480360360208110156107b957600080fd5b5035611a26565b6040805192835260208301919091528051918290030190f35b6107f6600480360360208110156107ef57600080fd5b5035611a3f565b604080519115158252519081900360200190f35b6106456004803603606081101561082057600080fd5b50803590602081013590604001351515611a7a565b6106456004803603602081101561084b57600080fd5b810190602081018135600160201b81111561086557600080fd5b82018360208201111561087757600080fd5b803590602001918460208302840111600160201b8311171561089857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611c90945050505050565b610645600480360360208110156108ec57600080fd5b5035611cb8565b61068d600480360360a081101561090957600080fd5b8135916020810135916040820135916001600160a01b036060820135169181019060a081016080820135600160201b81111561094457600080fd5b82018360208201111561095657600080fd5b803590602001918460608302840111600160201b8311171561097757600080fd5b509092509050611d7a565b61071f61208b565b61068d61209a565b6109af600480360360208110156109a857600080fd5b50356120a0565b604051808e81526020018d81526020018c81526020018b81526020018a8152602001896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b03168152602001876003811115610a0d57fe5b60ff1681526020018681526020018581526020018481526020018381526020018281526020019d505050505050505050505050505060405180910390f35b61068d60048036036020811015610a6157600080fd5b50356001600160a01b0316612111565b61068d60048036036020811015610a8757600080fd5b5035612123565b61068d612163565b61068d612169565b61064560048036036080811015610ab457600080fd5b508035906001600160a01b0360208201358116916040810135909116906060013561216f565b61068d60048036036020811015610af057600080fd5b50356001600160a01b03166121f6565b61068d61232d565b61068d612333565b610645600480360360a0811015610b2657600080fd5b6001600160a01b0382351691602081013591604082013591606081013515159181019060a081016080820135600160201b811115610b6357600080fd5b820183602082011115610b7557600080fd5b803590602001918460018302840111600160201b83111715610b9657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612339945050505050565b610645600480360360c0811015610bed57600080fd5b6001600160a01b038235169160208101359160408201359160608101359160808201351515919081019060c0810160a0820135600160201b811115610c3157600080fd5b820183602082011115610c4357600080fd5b803590602001918460018302840111600160201b83111715610c6457600080fd5b5090925090506123fa565b610c8c60048036036020811015610c8557600080fd5b5035612519565b60405180868152602001858152602001846001600160a01b03166001600160a01b031681526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610cf7578181015183820152602001610cdf565b50505050905090810190601f168015610d245780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b6107f66125df565b61068d6125e8565b61071f60048036036020811015610d5c57600080fd5b50356125ee565b61071f61260c565b61071f612620565b61068d60048036036020811015610d8957600080fd5b810190602081018135600160201b811115610da357600080fd5b820183602082011115610db557600080fd5b803590602001918460018302840111600160201b83111715610dd657600080fd5b509092509050612630565b61064560048036036060811015610df757600080fd5b5080359060208101359060400135612951565b61071f60048036036020811015610e2057600080fd5b50356129ba565b61064560048036036040811015610e3d57600080fd5b506001600160a01b038135169060200135612a06565b61064560048036036060811015610e6957600080fd5b813591602081013591810190606081016040820135600160201b811115610e8f57600080fd5b820183602082011115610ea157600080fd5b803590602001918460018302840111600160201b83111715610ec257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612a1b945050505050565b6107f660048036036060811015610f1957600080fd5b50803590602081013590604001356001600160a01b0316612ae6565b61068d612b83565b610645612b89565b61068d612be4565b61068d612bea565b61068d60048036036020811015610f6b57600080fd5b50356001600160a01b0316612bf0565b61071f612c02565b61068d612c11565b61068d612c17565b61068d60048036036020811015610fa957600080fd5b5035612c1d565b61068d60048036036020811015610fc657600080fd5b5035612c74565b61068d612c89565b61068d612c8f565b61064560048036036040811015610ff357600080fd5b5080359060200135612c95565b61071f612cdb565b61071f612cef565b6107f6612cfe565b61068d612d41565b6106456004803603602081101561103657600080fd5b5035612d47565b61068d612d5e565b6106456004803603602081101561105b57600080fd5b5035612d64565b61071f612d81565b6106456004803603604081101561108057600080fd5b5080359060200135612d90565b61068d612df6565b610645600480360360208110156110ab57600080fd5b5035612dfc565b610645600480360360408110156110c857600080fd5b5080359060200135612eb8565b610645600480360360408110156110eb57600080fd5b5080359060200135612f1e565b6106456004803603602081101561110e57600080fd5b5035613011565b61068d613028565b6106456004803603608081101561113357600080fd5b813591602081013591604082013515159190810190608081016060820135600160201b81111561116257600080fd5b82018360208201111561117457600080fd5b803590602001918460018302840111600160201b8311171561119557600080fd5b50909250905061302e565b6106456130e6565b61068d6130f8565b61068d6130fe565b610645600480360360408110156111ce57600080fd5b506001600160a01b038135169060200135613104565b610645600480360360408110156111fa57600080fd5b5080359060200135613116565b61068d6004803603602081101561121d57600080fd5b5035613129565b6107f66004803603606081101561123a57600080fd5b50803590602081013590604001356001600160a01b0316613177565b6106456004803603604081101561126c57600080fd5b50803590602001356001600160a01b03166132df565b6106456004803603602081101561129857600080fd5b503561339a565b61068d613423565b6107f6613429565b610645600480360360208110156112c557600080fd5b50351515613432565b61068d600480360360208110156112e457600080fd5b5035613584565b6106456004803603602081101561130157600080fd5b5035613596565b6106456004803603604081101561131e57600080fd5b508035906020013561377c565b61068d6137e4565b6107c06137ea565b6106456004803603602081101561135157600080fd5b50356137f3565b6106456004803603602081101561136e57600080fd5b50356001600160a01b03166138af565b61068d6004803603602081101561139457600080fd5b503561392f565b61071f613941565b610645600480360360208110156113b957600080fd5b50351515613950565b610645600480360360208110156113d857600080fd5b50356001600160a01b031661396b565b610645600480360360408110156113fe57600080fd5b81359190810190604081016020820135600160201b81111561141f57600080fd5b82018360208201111561143157600080fd5b803590602001918460018302840111600160201b8311171561145257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550613985945050505050565b61064560048036036101208110156114aa57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c082013581169160e08101358216916101009091013516613b8a565b6106456004803603602081101561151357600080fd5b5035613d2d565b610645613d48565b61071f613d58565b6106456004803603606081101561154057600080fd5b5080359060208101359060400135613d67565b61068d613e82565b61071f613e88565b61156b613e97565b600f55565b611578613e97565b61158181613ee5565b61158a57600080fd5b60238054610100600160a81b0319169055602580546001600160a01b03199081166001600160a01b03938416179091556006805482169583169590951790945560058054851693821693909317909255600780549093169116179055565b60155481565b60135481565b60085481565b611602613e97565b8061160c57600080fd5b60055460105460408051630f1980a560e41b8152600481018590526024810192909252516001600160a01b039092169163f1980a509160448082019260009290919082900301818387803b15801561166357600080fd5b505af1158015611677573d6000803e3d6000fd5b50505060109190915550565b60065460408051632f745c5960e01b81526001600160a01b038481166004830152600060248301819052925192931691632f745c5991604480820192602092909190829003018186803b1580156116d957600080fd5b505afa1580156116ed573d6000803e3d6000fd5b505050506040513d602081101561170357600080fd5b505190505b919050565b8061171781613f04565b60026000838152601a6020526040902060060154600160a01b900460ff16600381111561174057fe5b1461177f576040805162461bcd60e51b815260206004820152600a602482015269139bdd081a985a5b195960b21b604482015290519081900360640190fd5b6000828152601a6020526040902060030154156117d7576040805162461bcd60e51b8152602060048201526011602482015270416c726561647920756e7374616b696e6760781b604482015290519081900360640190fd5b6009546000838152601a6020526040902060040154811015611839576040805162461bcd60e51b8152602060048201526016602482015275125b98dbdb5c1b195d19481a985a5b081c195c9a5bd960521b604482015290519081900360640190fd5b6000838152601a6020526040902054600c5481101561185757600080fd5b6000848152601a60205260409020600601546001600160a01b031680156118cc57806001600160a01b031663a69df4b56040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156118b357600080fd5b505af11580156118c7573d6000803e3d6000fd5b505050505b6000858152601a60205260409020600a01546118fc906118f390849063ffffffff613f8e16565b60016000613fa0565b6000858152601a602052604080822060068101805460ff60a01b1916600160a01b1790556005908101549054825163f92ec5af60e01b8152600481018a90526001600160a01b039283166024820181905293519394929091169263f92ec5af9260448084019391929182900301818387803b15801561197a57600080fd5b505af115801561198e573d6000803e3d6000fd5b50505050505050505050565b60175481565b6007546001600160a01b031681565b6119b7613e97565b600955565b6119c4613e97565b6001600160a01b0381166119d757600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60268181548110611a0657fe5b6000918252602090912001546001600160a01b0316905081565b600e5481565b601e602052600090815260409020805460019091015482565b6000818152601a6020526040812060068101548154600390920154600954611a7493600160a01b90930460ff1692919061405c565b92915050565b611a82614094565b82611a8c81613f04565b6000848152601a602052604090206003015415611adf576040805162461bcd60e51b815260206004820152600c60248201526b4e6f2072657374616b696e6760a01b604482015290519081900360640190fd5b8215611af057611af03330856140d5565b611af9846141a7565b8115611b4c576000848152601a60205260409020600190810154611b359190611b2990869063ffffffff613f8e16565b9063ffffffff6141b616565b6000858152601a6020526040902060019081015592505b601154600090611b62908563ffffffff613f8e16565b60118190556000868152601a6020526040902054909150611b89908563ffffffff613f8e16565b6000868152601a6020526040812091909155611ba790859080613fa0565b6005546040805163532e19a960e01b81526004810188905290516001600160a01b039092169163532e19a99160248082019260009290919082900301818387803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b50506005546000888152601a6020526040808220548151631585a9f360e21b8152600481018c905260248101919091526044810187905290516001600160a01b039093169450635616a7cc93506064808201939182900301818387803b158015611c7157600080fd5b505af1158015611c85573d6000803e3d6000fd5b505050505050505050565b611c98612cfe565b611ca157600080fd5b8051611cb4906026906020840190615c9c565b5050565b80611cc281613f04565b600082815260208052604090205415611cda57600080fd5b6000828152601a602052604090206006810154600290910154600160a01b90910460ff169015801590611d1c57506000838152601a6020526040902060030154155b8015611d4857506001816003811115611d3157fe5b1480611d4857506002816003811115611d4657fe5b145b611d5157600080fd5b600954600090611d6890600163ffffffff613f8e16565b9050611d7484826141cb565b50505050565b6002546000906001600160a01b03163314611d9457600080fd5b600954601d546000908190611da7615d01565b6026546040805191840180835260208082028401019091528015611dd5578160200160208202803883390190505b5060408083019190915260268054825160208083028201810190945281815292830182828015611e2e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611e10575b50505050506060820152600060208201526026546080820152611e4f615d30565b6026546040805191850180835260208082028401019091528015611e7d578160200160208202803883390190505b50602082015260005b8881101561204c576000611ed48e8c8c85818110611ea057fe5b905060600201600380602002604051908101604052809291908260036020028082843760009201919091525061434f915050565b9050856001600160a01b0316816001600160a01b03161415611ef65750612044565b856001600160a01b0316816001600160a01b03161015611f16575061204c565b6001600160a01b0381166000908152601b6020908152604080832054808452601a909252909120805460068201546003909201548087529091600160a01b900460ff1690611f6890829084908e61405c565b15611ff3576000838152601a60205260409020600a01549398508893611fa7908390611f9b908d9063ffffffff613f8e16565b9063ffffffff613f8e16565b8651909a5015611fe157828660200151876040015181518110611fc657fe5b60209081029190910101526040860180516001019052611fee565b611feb8785614452565b96505b61203f565b600281600381111561200157fe5b141561203f5782876040015188600001518151811061201c57fe5b602090810291909101810191909152875160019081018952908801805190910190525b505050505b600101611e86565b50612058826000614452565b915061207a8d8b878e866040015187600001518760200151886040015161452f565b9d9c50505050505050505050505050565b6006546001600160a01b031681565b60165481565b601a60205260009081526040902080546001820154600283015460038401546004850154600586015460068701546007880154600889015460098a0154600a8b0154600b909b0154999a98999798969795966001600160a01b039586169695851695600160a01b90950460ff16948d565b601b6020526000908152604090205481565b60008061212f83614697565b6000858152601a602052604090206009015490925061215c9150600190611b29908463ffffffff613f8e16565b9392505050565b600c5481565b60295481565b612177613e97565b6000848152601a60205260409020600601546001600160a01b03168061219c57600080fd5b6040805163abf59fc960e01b81526001600160a01b03868116600483015285811660248301526044820185905291519183169163abf59fc99160648082019260009290919082900301818387803b158015611c7157600080fd5b60006001600160a01b03821615806122845750600654604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b15801561225657600080fd5b505afa15801561226a573d6000803e3d6000fd5b505050506040513d602081101561228057600080fd5b5051155b1561229157506000611708565b60065460408051632f745c5960e01b81526001600160a01b0385811660048301526000602483018190529251601a949190911691632f745c59916044808301926020929190829003018186803b1580156122ea57600080fd5b505afa1580156122fe573d6000803e3d6000fd5b505050506040513d602081101561231457600080fd5b5051815260208101919091526040016000205492915050565b600f5481565b60105481565b612341614094565b60105461234c612c89565b1061238e576040805162461bcd60e51b815260206004820152600d60248201526c6e6f206d6f726520736c6f747360981b604482015290519081900360640190fd5b600c548410156123da576040805162461bcd60e51b81526020600482015260126024820152711b9bdd08195b9bdd59da0819195c1bdcda5d60721b604482015290519081900360640190fd5b6123e685338587614713565b6123f2858584846147fd565b505050505050565b33301461243c576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6124498788886000614713565b612455856009546141cb565b600061249988868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506147fd92505050565b6005546040805163e12ab1af60e01b815260048101849052602481018a90526044810189905290519293506001600160a01b039091169163e12ab1af9160648082019260009290919082900301818387803b1580156124f757600080fd5b505af115801561250b573d6000803e3d6000fd5b505050505050505050505050565b60208080526000918252604091829020805460018083015460028085015460038601805489516101009682161596909602600019011692909204601f8101889004880285018801909852878452939691956001600160a01b03851695600160a01b90950460ff16949392908301828280156125d55780601f106125aa576101008083540402835291602001916125d5565b820191906000526020600020905b8154815290600101906020018083116125b857829003601f168201915b5050505050905085565b60195460ff1681565b60125481565b6000908152601a60205260409020600601546001600160a01b031690565b60005461010090046001600160a01b031681565b6004546001600160a01b03165b90565b6004805460408051631ab0168360e31b8152905160009333936001600160a01b03169263d580b4189281830192602092829003018186803b15801561267457600080fd5b505afa158015612688573d6000803e3d6000fd5b505050506040513d602081101561269e57600080fd5b50516001600160a01b0316146126ef576040805162461bcd60e51b81526020600482015260116024820152702737ba1039b630b9b41036b0b730b3b2b960791b604482015290519081900360640190fd5b606061273861273385858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250614c0a92505050565b614c2f565b90506000806000805b845181101561292557606061276886838151811061275b57fe5b6020026020010151614c2f565b905060006127898260008151811061277c57fe5b6020026020010151614d00565b9050612794816141a7565b60006127a68360018151811061277c57fe5b90506127b8858263ffffffff613f8e16565b6000838152601a60205260409020600601549095506001600160a01b03168015612886576000838152601a602090815260408083208054600a9091015482516306cbb60560e41b8152600481019290925260248201526044810186905290516001600160a01b03851692636cbb6050926064808201939182900301818787803b15801561284457600080fd5b505af1158015612858573d6000803e3d6000fd5b505050506040513d602081101561286e57600080fd5b50519050612882838263ffffffff6141b616565b9250505b6000838152601a60205260408120546128a5908463ffffffff6141b616565b6000858152601a602052604090208190559050806128ce576128c9846009546141cb565b612914565b6128eb856002815181106128de57fe5b6020026020010151614d60565b156129145761290b6128fe856001614d94565b899063ffffffff613f8e16565b60019099019897505b505060019093019250612741915050565b612946612938838563ffffffff613f8e16565b600003856000036000613fa0565b509695505050505050565b612959613e97565b60255460408051602481018690526044810185905260648082018590528251808303909101815260849091019091526020810180516001600160e01b0316633064689160e11b1790526129b5916001600160a01b031690614ede565b505050565b600654604080516331a9108f60e11b81526004810184905290516000926001600160a01b031691636352211e916024808301926020929190829003018186803b1580156116d957600080fd5b612a0e614094565b611cb48233836000614713565b601754604080513360208083019190915281830187905282518083038401815260609092019092528051910120612a5a9184908463ffffffff614f0616565b612a9d576040805162461bcd60e51b815260206004820152600f60248201526e2bb937b7339030b1b190383937b7b360891b604482015290519081900360640190fd5b336000908152601f6020526040812054612abe90859063ffffffff6141b616565b9050612aca338261505c565b336000818152601f60205260409020859055611d7490826150db565b600083612af2816151a0565b600354604080516323b872dd60e01b81526001600160a01b03868116600483015230602483015260448201889052915191909216916323b872dd9160648083019260209291908290030181600087803b158015612b4e57600080fd5b505af1158015612b62573d6000803e3d6000fd5b505050506040513d6020811015612b7857600080fd5b505195945050505050565b600a5481565b612b91612cfe565b612b9a57600080fd5b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b60095481565b60185481565b601f6020526000908152604090205481565b6004546001600160a01b031681565b602a5481565b600b5481565b600081612c29816151a0565b612c32836141a7565b6000838152601a6020526040812060090154612c5590600163ffffffff6141b616565b6000858152601a60205260409020600160099091015592505050919050565b6000908152601a60205260409020600a015490565b601d5490565b60115481565b81612c9f816151a0565b6000838152601a60205260409020600a0154612cc1908363ffffffff6141b616565b6000938452601a6020526040909320600a01929092555050565b60235461010090046001600160a01b031681565b6001546001600160a01b031690565b604080517f6d617469632e6e6574776f726b2e70726f78792e6f776e6572000000000000008152905190819003601901902054336001600160a01b039091161490565b60095490565b612d4f613e97565b612d5b816009546141cb565b50565b60275481565b80612d6e81613f04565b612d77826141a7565b611cb4823361520e565b6002546001600160a01b031681565b612d98614094565b602554604080516024810185905260448101849052306064808301919091528251808303909101815260849091019091526020810180516001600160e01b031663561ad5c960e11b179052611cb4916001600160a01b031690614ede565b60225481565b612e04613e97565b6005546016546040805163a3b1d8cb60e01b8152600481018590526024810192909252516001600160a01b039092169163a3b1d8cb9160448082019260009290919082900301818387803b158015612e5b57600080fd5b505af1158015612e6f573d6000803e3d6000fd5b505050506064811115612eb3576040805162461bcd60e51b8152602060048201526007602482015266746f6f2062696760c81b604482015290519081900360640190fd5b601655565b612ec0612cfe565b612ec957600080fd5b602554604080516024810185905260448082018590528251808303909101815260649091019091526020810180516001600160e01b0316639ddbbf8560e01b179052611cb4916001600160a01b031690614ede565b81612f28816151a0565b6000821315612f815760195460ff16612f81576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b6000838152601a602052604090206003015480612fa957612fa483600080613fa0565b612fec565b600954811115612fec576040805162461bcd60e51b8152602060048201526009602482015268756e7374616b696e6760b81b604482015290519081900360640190fd5b6000831261300357612ffe84846152cf565b611d74565b611d74848460001902612c95565b613019613e97565b8061302357600080fd5b600e55565b601c5490565b613036614094565b6025546040516024810187815260448201879052851515606483015260806084830190815260a483018590526130df936001600160a01b03169263a685487760e01b928a928a928a928a928a9260c40184848082843760008184015260408051601f19601f9093018316909401848103909201845252506020810180516001600160e01b03199a909a166001600160e01b03909a169990991790985250614ede95505050505050565b5050505050565b6130ee613e97565b6130f661530a565b565b60085490565b60245481565b61310c613e97565b611cb482826150db565b61311e613e97565b600c91909155600d55565b6000818152601a6020526040812060030154819061314e5761314a83614697565b5090505b6000838152601a6020526040902060019081015461215c9190611b29908463ffffffff613f8e16565b6000838152601a60205260408120600601546001600160a01b031633148061321657506004805460408051631ab0168360e31b8152905133936001600160a01b039093169263d580b41892808201926020929091829003018186803b1580156131df57600080fd5b505afa1580156131f3573d6000803e3d6000fd5b505050506040513d602081101561320957600080fd5b50516001600160a01b0316145b613255576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6003546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018790529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156132ab57600080fd5b505af11580156132bf573d6000803e3d6000fd5b505050506040513d60208110156132d557600080fd5b5051949350505050565b6132e7613e97565b306001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561332a57600080fd5b505afa15801561333e573d6000803e3d6000fd5b505050506040513d602081101561335457600080fd5b50516001600160a01b03161461336957600080fd5b6000918252601a602052604090912060060180546001600160a01b0319166001600160a01b03909216919091179055565b6133a2613e97565b806133ac57600080fd5b600554600b5460408051632dbe9d3160e21b8152600481018590526024810192909252516001600160a01b039092169163b6fa74c49160448082019260009290919082900301818387803b15801561340357600080fd5b505af1158015613417573d6000803e3d6000fd5b505050600b9190915550565b60145481565b60005460ff1681565b336000908152601b6020908152604080832054808452601a9092529091206006810154815460039092015460095461347793600160a01b90930460ff1692919061405c565b6134b8576040805162461bcd60e51b815260206004820152600d60248201526c3737ba103b30b634b230ba37b960991b604482015290519081900360640190fd5b6000818152601a60205260409020600601546001600160a01b03168061351e576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b604080516303dd464160e51b8152841515600482015290516001600160a01b03831691637ba8c82091602480830192600092919082900301818387803b15801561356757600080fd5b505af115801561357b573d6000803e3d6000fd5b50505050505050565b60216020526000908152604090205481565b806135a081613f04565b6000828152601a602052604090206003015480158015906135d657506009546008546135d390839063ffffffff613f8e16565b11155b8015613609575060036000848152601a6020526040902060060154600160a01b900460ff16600381111561360657fe5b14155b61361257600080fd5b6000838152601a6020526040812054601154909190613637908363ffffffff6141b616565b60118190559050613648853361520e565b60065460408051630852cd8d60e31b81526004810188905290516001600160a01b03909216916342966c689160248082019260009290919082900301818387803b15801561369557600080fd5b505af11580156136a9573d6000803e3d6000fd5b5050506000868152601a6020526040812081815560048101919091556005810180546001600160a01b03191690556000197f584f46c60af19681376031579adb04a2416e54ee5505351c2a8435e3766026ea55600601805460ff60a01b1916600360a01b1790555061371b33836150db565b6005546040805163ae2e26b160e01b815233600482015260248101889052604481018590526064810184905290516001600160a01b039092169163ae2e26b19160848082019260009290919082900301818387803b158015611c7157600080fd5b8161378681613f04565b61378f836141a7565b602554604080516024810186905260448082018690528251808303909101815260649091019091526020810180516001600160e01b0316636e6cb15960e11b1790526129b5916001600160a01b031690614ede565b60285481565b601c54601d5482565b6137fb613e97565b6000811161380857600080fd5b600554600a5460408051635071805360e11b8152600481018590526024810192909252516001600160a01b039092169163a0e300a69160448082019260009290919082900301818387803b15801561385f57600080fd5b505af1158015613873573d6000803e3d6000fd5b505050600a82905550600881905561389281600463ffffffff61531616565b60158190556009546138a99163ffffffff613f8e16565b60185550565b6138b7612cfe565b6138c057600080fd5b6001600160a01b0381166138d357600080fd5b6002546040516001600160a01b038084169216907f211c9015fc81c0dbd45bd99f0f29fc1c143bfd53442d5ffd722bbbef7a887fe990600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000908152601a602052604090205490565b6005546001600160a01b031681565b613958613e97565b6019805460ff1916911515919091179055565b613973612cfe565b61397c57600080fd5b612d5b81615338565b8161398f81613f04565b600061399a836153a7565b600954600f5460008781526021602052604090205492935090916139c39163ffffffff613f8e16565b811015613a05576040805162461bcd60e51b815260206004820152600b60248201526a139bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6000858152601a602090815260408083206005908101549054915163b80fbce560e01b8152600481018a81526001600160a01b039283166024830181905288841660448401526080606484019081528b5160848501528b519197949095169563b80fbce5958d9589958c958f95909460a490920192918601918190849084905b83811015613a9d578181015183820152602001613a85565b50505050905090810190601f168015613aca5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015613aec57600080fd5b505af1158015613b00573d6000803e3d6000fd5b5050506000878152601a602052604090206003015415159050613b2f57613b2681615460565b613b2f8361556a565b6001600160a01b039081166000908152601b60209081526040808320600019905594909216808252848220889055968152601a825283812060050180546001600160a01b031916909717909655602190529320929092555050565b60235460ff1615613bd3576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6023805460ff19166001179055613be981613ee5565b613c33576040805162461bcd60e51b8152602060048201526016602482015275185d58dd1a5bdb881a5b5c1b081a5b98dbdc9c9958dd60521b604482015290519081900360640190fd5b602580546001600160a01b03199081166001600160a01b038481169190911790925560008054610100600160a81b031916610100878516021790556004805482168c84161790556002805482168b84161790556003805482168a841617905560068054821689841617905560058054821688841617905560078054909116918616919091179055613cc382615338565b5050612000600855505060016009819055610376600a90815569044664c7bf6451f00000600b55670de0b6b3a7640000600c819055600d55610400600e556064600f55600760105560128290556108006015556016556019805460ff191690911790555050505050565b613d35613e97565b6009546138a9908263ffffffff613f8e16565b613d50613e97565b6130f6615684565b6025546001600160a01b031681565b60078211613db0576040805162461bcd60e51b815260206004820152601160248201527024b73b30b634b21036b4b3b930ba34b7b760791b604482015290519081900360640190fd5b6000838152601a6020526040808220600601548151636e7ce59160e01b81523360048201526024810185905291516001600160a01b0390911692636e7ce591926044808201939182900301818387803b158015613e0c57600080fd5b505af1158015613e20573d6000803e3d6000fd5b5050506000838152601a6020526040808220600601548151632830728d60e21b81523360048201526024810186905291516001600160a01b03909116935063a0c1ca349260448084019391929182900301818387803b15801561356757600080fd5b600d5481565b6003546001600160a01b031681565b60005461010090046001600160a01b031633146130f65760405162461bcd60e51b8152600401808060200182810382526026815260200180615dce6026913960400191505060405180910390fd5b60006001600160a01b038216613efd57506000611708565b503b151590565b600654604080516331a9108f60e11b815260048101849052905133926001600160a01b031691636352211e916024808301926020929190829003018186803b158015613f4f57600080fd5b505afa158015613f63573d6000803e3d6000fd5b505050506040513d6020811015613f7957600080fd5b50516001600160a01b031614612d5b57600080fd5b60008282018381101561215c57600080fd5b8061403a576000831315613fc957601c54613fc1908463ffffffff613f8e16565b601c55613fed565b6000831215613fed57601c54613fe990600085900363ffffffff6141b616565b601c555b600082131561401157601d54614009908363ffffffff613f8e16565b601d55614035565b600082121561403557601d5461403190600084900363ffffffff6141b616565b601d555b6129b5565b6000818152601e60205260409020805484018155600101805483019055505050565b60008084118015614074575082158061407457508183115b801561408b5750600185600381111561408957fe5b145b95945050505050565b60005460ff16156130f6576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b600354604080516323b872dd60e01b81526001600160a01b038681166004830152858116602483015260448201859052915191909216916323b872dd9160648083019260209291908290030181600087803b15801561413357600080fd5b505af1158015614147573d6000803e3d6000fd5b505050506040513d602081101561415d57600080fd5b50516129b5576040805162461bcd60e51b81526020600482015260146024820152731d1c985b9cd9995c88199c9bdb4819985a5b195960621b604482015290519081900360640190fd5b612d5b81602454602454615693565b6000828211156141c557600080fd5b50900390565b6141d4826141a7565b6000828152601a6020526040812054906141ed846129ba565b6000858152601a6020526040902060038101859055600a810154600690910154919250906001600160a01b0316801561427457806001600160a01b031663f83d08ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561425b57600080fd5b505af115801561426f573d6000803e3d6000fd5b505050505b6000868152601a6020526040902060050154614298906001600160a01b0316615460565b6142a2868461520e565b60006009548611156142b457856142b7565b60005b90506142cb83860160000360001983613fa0565b60055460408051635e04d48360e01b81526001600160a01b038781166004830152602482018b9052604482018a90526064820189905291519190921691635e04d48391608480830192600092919082900301818387803b15801561432e57600080fd5b505af1158015614342573d6000803e3d6000fd5b5050505050505050505050565b805160208201516040830151600092919060ff167f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156143975760009350505050611a74565b601b8160ff1610156143a757601b015b8060ff16601b141580156143bf57508060ff16601c14155b156143d05760009350505050611a74565b60408051600080825260208083018085528a905260ff85168385015260608301879052608083018690529251909260019260a080820193601f1981019281900390910190855afa158015614428573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661444857600080fd5b9695505050505050565b61445a615d01565b8260800151836020015110801561449e5750816001600160a01b0316836060015184602001518151811061448a57fe5b60200260200101516001600160a01b031614155b1561451f57601b600084606001518560200151815181106144bb57fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205483604001518460000151815181106144f857fe5b6020908102919091018101919091528351600190810185529084018051909101905261445a565b5050602081018051600101905290565b601c5460009061455c6001611f9b600361455085600263ffffffff61573416565b9063ffffffff61531616565b8810156145a6576040805162461bcd60e51b8152602060048201526013602482015272322f332b31206e6f6e2d6d616a6f726974792160681b604482015290519081900360640190fd5b60006145b38b8a8461575b565b905060006145d160646145506016548561573490919063ffffffff16565b6001600160a01b038c166000908152601b6020908152604080832054808452601a90925290912060018101549293509091614612908463ffffffff613f8e16565b600182015560178b9055600061465f6146508e6145506a084595161401484a0000006146448a8a63ffffffff6141b616565b9063ffffffff61573416565b6024549063ffffffff613f8e16565b905061466c8b8b836158af565b602481905561467c8989836158af565b6146846158e3565b50929d9c50505050505050505050505050565b6000818152601a602052604081208054600a9091015482919082906146c390839063ffffffff613f8e16565b6000868152601a60205260409020600b0154602454919250900361470786846147016a084595161401484a000000614550868863ffffffff61573416565b85615958565b94509450505050915091565b600d5482101561475a576040805162461bcd60e51b815260206004820152600d60248201526c199959481d1bdbc81cdb585b1b609a1b604482015290519081900360640190fd5b614774833061476f858563ffffffff613f8e16565b6140d5565b602254614787908363ffffffff613f8e16565b6022556005546040805163a449d79560e01b81526001600160a01b038781166004830152602482018690529151919092169163a449d79591604480830192600092919082900301818387803b1580156147df57600080fd5b505af11580156147f3573d6000803e3d6000fd5b5050505050505050565b600080614809836153a7565b600954601254600554601154939450919290916001600160a01b031690600090614839908a63ffffffff613f8e16565b905080601181905550604051806101a001604052808a8152602001600181526020018581526020016000815260200160008152602001866001600160a01b031681526020018961488a576000614916565b600754600480546040805163d4ad267360e01b81529283018990526001600160a01b03888116602485015291821660448401525192169163d4ad2673916064808201926020929091908290030181600087803b1580156148e957600080fd5b505af11580156148fd573d6000803e3d6000fd5b505050506040513d602081101561491357600080fd5b50515b6001600160a01b031681526020016001815260006020808301829052604080840183905260016060808601829052608080870186905260245460a0978801528a8652601a855294839020875181559387015191840191909155908501516002830155840151600380830191909155918401516004820155918301516005830180546001600160a01b039283166001600160a01b03199182161790915560c08501516006850180549190931691161780825560e08501519260ff60a01b1990911690600160a01b9084908111156149e857fe5b0217905550610100820151600782015561012082015160088201556101408201516009820155610160820151600a82015561018090910151600b9091015560008381526021602052604080822086905560065481516340c10f1960e01b81526001600160a01b038e8116600483015260248201889052925192909116926340c10f199260448084019382900301818387803b158015614a8657600080fd5b505af1158015614a9a573d6000803e3d6000fd5b5050506001600160a01b0386166000908152601b60205260408120859055614ac791508a90600190613fa0565b836020600085815260200190815260200160002060010181905550816001600160a01b03166333a8383c868986888e876040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b0316815260200180602001868152602001858152602001848152602001838152602001828103825287818151815260200191508051906020019080838360005b83811015614b73578181015183820152602001614b5b565b50505050905090810190601f168015614ba05780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b158015614bc457600080fd5b505af1158015614bd8573d6000803e3d6000fd5b50505050614bf0600184613f8e90919063ffffffff16565b601255614bfc8561556a565b509098975050505050505050565b614c12615d51565b506040805180820190915281518152602082810190820152919050565b6060614c3a826159ec565b614c4357600080fd5b6000614c4e83615a26565b9050606081604051908082528060200260200182016040528015614c8c57816020015b614c79615d51565b815260200190600190039081614c715790505b5090506000614c9e8560200151615a82565b60208601510190506000805b84811015614cf557614cbb83615ae5565b9150604051806040016040528083815260200184815250848281518110614cde57fe5b602090810291909101015291810191600101614caa565b509195945050505050565b805160009015801590614d1557508151602110155b614d1e57600080fd5b6000614d2d8360200151615a82565b83516020808601518301805193945091849003929190831015614d5757826020036101000a820491505b50949350505050565b8051600090600114614d7157600080fd5b6020820151805160001a908115614d89576001614d8c565b60005b949350505050565b6000828152601a60205260408120600601546001600160a01b03168015614e0957806001600160a01b031663f83d08ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015614df057600080fd5b505af1158015614e04573d6000803e3d6000fd5b505050505b600954614e1c818563ffffffff613f8e16565b6000868152601a602052604080822060048082019490945560068101805460ff60a01b1916600160a11b1790556005805491015482516381dc101b60e01b81529485018a9052602485018690526001600160a01b03908116604486015291519116926381dc101b92606480830193919282900301818387803b158015614ea157600080fd5b505af1158015614eb5573d6000803e3d6000fd5b5050506000868152601a60205260409020600a810154905461408b92509063ffffffff613f8e16565b600080825160208401856127105a03f43d604051816000823e828015614f02578282f35b8282fd5b60006020825181614f1357fe5b0615614f5d576040805162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840e0e4dedecc40d8cadccee8d60631b604482015290519081900360640190fd5b60006020835181614f6a57fe5b0490508060020a8510614fbc576040805162461bcd60e51b81526020600482015260156024820152744c65616620696e64657820697320746f6f2062696760581b604482015290519081900360640190fd5b60008660205b8551811161504e578581015192506002880661500e5781836040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209150615040565b828260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091505b600288049750602001614fc2565b509094149695505050505050565b60225461506f908263ffffffff6141b616565b6022556005546040805163122b648160e01b81526001600160a01b038581166004830152602482018590529151919092169163122b648191604480830192600092919082900301818387803b1580156150c757600080fd5b505af11580156123f2573d6000803e3d6000fd5b6003546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561513157600080fd5b505af1158015615145573d6000803e3d6000fd5b505050506040513d602081101561515b57600080fd5b5051611cb4576040805162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b6000818152601a60205260409020600601546001600160a01b03163314612d5b576040805162461bcd60e51b815260206004820152601860248201527f496e76616c696420636f6e747261637420616464726573730000000000000000604482015290519081900360640190fd5b6000828152601a602052604081206001908101546152319163ffffffff6141b616565b601454909150615247908263ffffffff613f8e16565b6014556000838152601a60205260409020600181810155602454600b9091015561527182826150db565b60055460145460408051635b42d93560e11b815260048101879052602481018590526044810192909252516001600160a01b039092169163b685b26a9160648082019260009290919082900301818387803b15801561356757600080fd5b6000828152601a60205260409020600a01546152f1908263ffffffff613f8e16565b6000928352601a6020526040909220600a019190915550565b6000805460ff19169055565b600080821161532457600080fd5b600082848161532f57fe5b04949350505050565b6001600160a01b03811661534b57600080fd5b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b600081516040146153e9576040805162461bcd60e51b81526020600482015260076024820152663737ba10383ab160c91b604482015290519081900360640190fd5b815160208301206001600160a01b0381161580159061541e57506001600160a01b0381166000908152601b6020526040902054155b611a74576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b604482015290519081900360640190fd5b6026805490600090600019830183811061547657fe5b600091825260209091200154602680546001600160a01b0390921692509060001984019081106154a257fe5b600091825260209091200180546001600160a01b031916905560001982015b801561555957836001600160a01b0316826001600160a01b031614156154e657615559565b602660018203815481106154f657fe5b9060005260206000200160009054906101000a90046001600160a01b0316826026600184038154811061552557fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790559150600019016154c1565b506000198201611d74602682615d6b565b6026805460018101825560008290527f744a2cf8fd7008e3d53b67916e73460df9fa5214e3ef23dd4259ca09493a35940180546001600160a01b0319166001600160a01b0384161790555460001901805b801561563c576000602660018303815481106155d357fe5b6000918252602090912001546001600160a01b03908116915084168110156155fb575061563c565b806026838154811061560957fe5b600091825260209091200180546001600160a01b0319166001600160a01b039290921691909117905550600019016155bb565b8181146129b557826026828154811061565157fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6000805460ff19166001179055565b6000838152601a60205260409020600b015482811015615712576000848152601a602052604090208054600a9091015480156156fa5760006156db838363ffffffff613f8e16565b90506156f48784846156ef8b868c8b615b7e565b615ba2565b5061570f565b61570f8661570a88858988615b7e565b615c48565b50505b80821115611d74576000848152601a60205260409020600b0182905550505050565b60008261574357506000611a74565b8282028284828161575057fe5b041461215c57600080fd5b600e54600b54600091908261577b83888161577257fe5b04602954615c86565b905060008111801561578f57506027548114155b156157d057602754156157ca5760006064602a548402816157ac57fe5b0490508160275411156157c257918201916157c8565b80830392505b505b60278190555b6000838811156158695760285461581861580860646145506157fb6002600019890189020486615734565b889063ffffffff61573416565b611b29868663ffffffff61573416565b915061583a61582d848763ffffffff61573416565b8a9063ffffffff6141b616565b9850615865615858606461455084614644898963ffffffff61573416565b859063ffffffff6141b616565b9350505b61588d615880856145508b8763ffffffff61573416565b829063ffffffff613f8e16565b90506158a386614550838a63ffffffff61573416565b98975050505050505050565b60245460005b838110156130df576158db8582815181106158cc57fe5b60200260200101518385615693565b6001016158b5565b60095460006158f982600163ffffffff613f8e16565b9050615903615d51565b506000818152601e6020908152604080832081518083019092528054808352600190910154928201839052909261593a9290613fa0565b506000918252601e6020526040822082815560010191909155600955565b6000808261596b575060009050806159e3565b600061598184614550888863ffffffff61573416565b6000888152601a602052604090206007015490915080156159c8576159c56159b86064614550846146448b8863ffffffff6141b616565b839063ffffffff613f8e16565b91505b60006159da878463ffffffff6141b616565b92945091925050505b94509492505050565b80516000906159fd57506000611708565b6020820151805160001a9060c0821015615a1c57600092505050611708565b5060019392505050565b8051600090615a3757506000611708565b60008090506000615a4b8460200151615a82565b602085015185519181019250015b80821015615a7957615a6a82615ae5565b60019093019290910190615a59565b50909392505050565b8051600090811a6080811015615a9c576000915050611708565b60b8811080615ab7575060c08110801590615ab7575060f881105b15615ac6576001915050611708565b60c0811015615ada5760b519019050611708565b60f519019050611708565b80516000908190811a6080811015615b005760019150615b77565b60b8811015615b1557607e1981019150615b77565b60c0811015615b425760b78103600185019450806020036101000a85510460018201810193505050615b77565b60f8811015615b575760be1981019150615b77565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60008183036144486a084595161401484a000000614550838863ffffffff61573416565b6000615bb4838563ffffffff613f8e16565b9050600080615bc587878686615958565b90925090508015615c05576000878152601a6020526040902060090154615bf2908263ffffffff613f8e16565b6000888152601a60205260409020600901555b811561357b576000878152601a6020526040902060010154615c2d908363ffffffff613f8e16565b6000888152601a602052604090206001015550505050505050565b8015611cb4576000828152601a6020526040902060010154615c70908263ffffffff613f8e16565b6000838152601a60205260409020600101555050565b6000818310615c95578161215c565b5090919050565b828054828255906000526020600020908101928215615cf1579160200282015b82811115615cf157825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615cbc565b50615cfd929150615d8f565b5090565b6040518060a0016040528060008152602001600081526020016060815260200160608152602001600081525090565b60405180606001604052806000815260200160608152602001600081525090565b604051806040016040528060008152602001600081525090565b8154818355818111156129b5576000838152602090206129b5918101908301615db3565b61262d91905b80821115615cfd5780546001600160a01b0319168155600101615d95565b61262d91905b80821115615cfd5760008155600101615db956fe4f6e6c7920676f7665726e616e636520636f6e747261637420697320617574686f72697a6564a265627a7a7231582058be6eb435b22b31280540e2326580f39ea0fe929cd1983b8a5ad5d82a779e6764736f6c63430005110032
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106106235760003560e01c80637d66975211610336578063b1d23f02116101c3578063e6692f491161010f578063f5e95acb116100ad578063f8a3176c11610087578063f8a3176c14611522578063fb1ef52c1461152a578063fba58f3414611553578063fc0c546a1461155b57610623565b8063f5e95acb14611493578063f771fc87146114fd578063f83d08ba1461151a57610623565b8063f24ccbfe116100e9578063f24ccbfe1461139b578063f28699fa146113a3578063f2fde38b146113c2578063f41a9642146113e857610623565b8063e6692f491461133b578063e8afa8e814611358578063eceec1d31461137e57610623565b8063cf3090121161017c578063d86d53e711610156578063d86d53e7146112eb578063dcd962b214611308578063e568959a1461132b578063e59ee0c61461133357610623565b8063cf309012146112a7578063d6de07d0146112af578063d7f5549d146112ce57610623565b8063b1d23f02146111e4578063b65de35e14611207578063bc8756a914611224578063c710e92214611256578063cbf383d514611282578063cd6b83881461129f57610623565b8063987ab9db11610282578063a440ab1e1161023b578063a69df4b511610215578063a69df4b5146111a0578063a7ab6961146111a8578063a8dc889b146111b0578063b184be81146111b857610623565b8063a440ab1e146110f8578063a476907114611115578063a68548771461111d57610623565b8063987ab9db1461106257806399d18f6f1461106a5780639a8a62431461108d5780639b33f434146110955780639ddbbf85146110b25780639ff11500146110d557610623565b8063883b455f116102ef578063900cf0cf116102c9578063900cf0cf14611018578063914601491461102057806391f1a3a51461103d5780639342c8f41461104557610623565b8063883b455f146110005780638da5cb5b146110085780638f32d59b1461101057610623565b80637d66975214610f8b5780637ed4b27c14610f935780637f4b432314610fb05780637f952d9514610fcd578063817b1cd214610fd5578063858a7c0314610fdd57610623565b8063451b5985116104b45780635e47655f116104005780637060054d116103b957806377939d101161039357806377939d1014610f4d57806378f84a4414610f555780637b10399914610f7b5780637c7eaf1a14610f8357610623565b80637060054d14610f35578063715018a614610f3d5780637667180814610f4557610623565b80635e47655f14610d7357806360c8d12214610de15780636352211e14610e0a5780636365679814610e2757806368cb812a14610e535780636901b25314610f0357610623565b806352b8115d1161046d5780635508d8e1116104475780635508d8e114610d3e57806356342d8c14610d465780635aa6e67514610d635780635ab1bd5314610d6b57610623565b806352b8115d14610bd75780635325e14414610c6f57806354b8c60114610d3657610623565b8063451b598514610a9657806348ab8b2a14610a9e5780634b341aed14610ada5780634e3c83f114610b005780634fd101d714610b085780634fdd20f114610b1057610623565b806325316411116105735780632fa9d18b1161052c57806335aa2e441161050657806335aa2e44146109925780633862da0b14610a4b57806339610f7814610a7157806341b3d18514610a8e57610623565b80632fa9d18b146108f357806331c2273b14610982578063342745861461098a57610623565b8063253164111461079b57806325726df2146107a35780632649263a146107d957806328cc4e411461080a5780632cf44a43146108355780632e17de78146108d657610623565b8063174e6832116105e05780631ae4818f116105ba5780631ae4818f146107175780631dd6b9b11461073b5780631e9b12ef146107585780632079fb9a1461077e57610623565b8063174e6832146106cc578063178c2c83146106f257806317c2b9101461070f57610623565b806306cfb10414610628578063078a13b1146106475780630cccfc58146106855780630e15561a1461069f5780630ebb172a146106a757806316827b1b146106af575b600080fd5b6106456004803603602081101561063e57600080fd5b5035611563565b005b6106456004803603608081101561065d57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060013516611570565b61068d6115e8565b60408051918252519081900360200190f35b61068d6115ee565b61068d6115f4565b610645600480360360208110156106c557600080fd5b50356115fa565b61068d600480360360208110156106e257600080fd5b50356001600160a01b0316611683565b6106456004803603602081101561070857600080fd5b503561170d565b61068d61199a565b61071f6119a0565b604080516001600160a01b039092168252519081900360200190f35b6106456004803603602081101561075157600080fd5b50356119af565b6106456004803603602081101561076e57600080fd5b50356001600160a01b03166119bc565b61071f6004803603602081101561079457600080fd5b50356119f9565b61068d611a20565b6107c0600480360360208110156107b957600080fd5b5035611a26565b6040805192835260208301919091528051918290030190f35b6107f6600480360360208110156107ef57600080fd5b5035611a3f565b604080519115158252519081900360200190f35b6106456004803603606081101561082057600080fd5b50803590602081013590604001351515611a7a565b6106456004803603602081101561084b57600080fd5b810190602081018135600160201b81111561086557600080fd5b82018360208201111561087757600080fd5b803590602001918460208302840111600160201b8311171561089857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611c90945050505050565b610645600480360360208110156108ec57600080fd5b5035611cb8565b61068d600480360360a081101561090957600080fd5b8135916020810135916040820135916001600160a01b036060820135169181019060a081016080820135600160201b81111561094457600080fd5b82018360208201111561095657600080fd5b803590602001918460608302840111600160201b8311171561097757600080fd5b509092509050611d7a565b61071f61208b565b61068d61209a565b6109af600480360360208110156109a857600080fd5b50356120a0565b604051808e81526020018d81526020018c81526020018b81526020018a8152602001896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b03168152602001876003811115610a0d57fe5b60ff1681526020018681526020018581526020018481526020018381526020018281526020019d505050505050505050505050505060405180910390f35b61068d60048036036020811015610a6157600080fd5b50356001600160a01b0316612111565b61068d60048036036020811015610a8757600080fd5b5035612123565b61068d612163565b61068d612169565b61064560048036036080811015610ab457600080fd5b508035906001600160a01b0360208201358116916040810135909116906060013561216f565b61068d60048036036020811015610af057600080fd5b50356001600160a01b03166121f6565b61068d61232d565b61068d612333565b610645600480360360a0811015610b2657600080fd5b6001600160a01b0382351691602081013591604082013591606081013515159181019060a081016080820135600160201b811115610b6357600080fd5b820183602082011115610b7557600080fd5b803590602001918460018302840111600160201b83111715610b9657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612339945050505050565b610645600480360360c0811015610bed57600080fd5b6001600160a01b038235169160208101359160408201359160608101359160808201351515919081019060c0810160a0820135600160201b811115610c3157600080fd5b820183602082011115610c4357600080fd5b803590602001918460018302840111600160201b83111715610c6457600080fd5b5090925090506123fa565b610c8c60048036036020811015610c8557600080fd5b5035612519565b60405180868152602001858152602001846001600160a01b03166001600160a01b031681526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610cf7578181015183820152602001610cdf565b50505050905090810190601f168015610d245780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b6107f66125df565b61068d6125e8565b61071f60048036036020811015610d5c57600080fd5b50356125ee565b61071f61260c565b61071f612620565b61068d60048036036020811015610d8957600080fd5b810190602081018135600160201b811115610da357600080fd5b820183602082011115610db557600080fd5b803590602001918460018302840111600160201b83111715610dd657600080fd5b509092509050612630565b61064560048036036060811015610df757600080fd5b5080359060208101359060400135612951565b61071f60048036036020811015610e2057600080fd5b50356129ba565b61064560048036036040811015610e3d57600080fd5b506001600160a01b038135169060200135612a06565b61064560048036036060811015610e6957600080fd5b813591602081013591810190606081016040820135600160201b811115610e8f57600080fd5b820183602082011115610ea157600080fd5b803590602001918460018302840111600160201b83111715610ec257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612a1b945050505050565b6107f660048036036060811015610f1957600080fd5b50803590602081013590604001356001600160a01b0316612ae6565b61068d612b83565b610645612b89565b61068d612be4565b61068d612bea565b61068d60048036036020811015610f6b57600080fd5b50356001600160a01b0316612bf0565b61071f612c02565b61068d612c11565b61068d612c17565b61068d60048036036020811015610fa957600080fd5b5035612c1d565b61068d60048036036020811015610fc657600080fd5b5035612c74565b61068d612c89565b61068d612c8f565b61064560048036036040811015610ff357600080fd5b5080359060200135612c95565b61071f612cdb565b61071f612cef565b6107f6612cfe565b61068d612d41565b6106456004803603602081101561103657600080fd5b5035612d47565b61068d612d5e565b6106456004803603602081101561105b57600080fd5b5035612d64565b61071f612d81565b6106456004803603604081101561108057600080fd5b5080359060200135612d90565b61068d612df6565b610645600480360360208110156110ab57600080fd5b5035612dfc565b610645600480360360408110156110c857600080fd5b5080359060200135612eb8565b610645600480360360408110156110eb57600080fd5b5080359060200135612f1e565b6106456004803603602081101561110e57600080fd5b5035613011565b61068d613028565b6106456004803603608081101561113357600080fd5b813591602081013591604082013515159190810190608081016060820135600160201b81111561116257600080fd5b82018360208201111561117457600080fd5b803590602001918460018302840111600160201b8311171561119557600080fd5b50909250905061302e565b6106456130e6565b61068d6130f8565b61068d6130fe565b610645600480360360408110156111ce57600080fd5b506001600160a01b038135169060200135613104565b610645600480360360408110156111fa57600080fd5b5080359060200135613116565b61068d6004803603602081101561121d57600080fd5b5035613129565b6107f66004803603606081101561123a57600080fd5b50803590602081013590604001356001600160a01b0316613177565b6106456004803603604081101561126c57600080fd5b50803590602001356001600160a01b03166132df565b6106456004803603602081101561129857600080fd5b503561339a565b61068d613423565b6107f6613429565b610645600480360360208110156112c557600080fd5b50351515613432565b61068d600480360360208110156112e457600080fd5b5035613584565b6106456004803603602081101561130157600080fd5b5035613596565b6106456004803603604081101561131e57600080fd5b508035906020013561377c565b61068d6137e4565b6107c06137ea565b6106456004803603602081101561135157600080fd5b50356137f3565b6106456004803603602081101561136e57600080fd5b50356001600160a01b03166138af565b61068d6004803603602081101561139457600080fd5b503561392f565b61071f613941565b610645600480360360208110156113b957600080fd5b50351515613950565b610645600480360360208110156113d857600080fd5b50356001600160a01b031661396b565b610645600480360360408110156113fe57600080fd5b81359190810190604081016020820135600160201b81111561141f57600080fd5b82018360208201111561143157600080fd5b803590602001918460018302840111600160201b8311171561145257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550613985945050505050565b61064560048036036101208110156114aa57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c082013581169160e08101358216916101009091013516613b8a565b6106456004803603602081101561151357600080fd5b5035613d2d565b610645613d48565b61071f613d58565b6106456004803603606081101561154057600080fd5b5080359060208101359060400135613d67565b61068d613e82565b61071f613e88565b61156b613e97565b600f55565b611578613e97565b61158181613ee5565b61158a57600080fd5b60238054610100600160a81b0319169055602580546001600160a01b03199081166001600160a01b03938416179091556006805482169583169590951790945560058054851693821693909317909255600780549093169116179055565b60155481565b60135481565b60085481565b611602613e97565b8061160c57600080fd5b60055460105460408051630f1980a560e41b8152600481018590526024810192909252516001600160a01b039092169163f1980a509160448082019260009290919082900301818387803b15801561166357600080fd5b505af1158015611677573d6000803e3d6000fd5b50505060109190915550565b60065460408051632f745c5960e01b81526001600160a01b038481166004830152600060248301819052925192931691632f745c5991604480820192602092909190829003018186803b1580156116d957600080fd5b505afa1580156116ed573d6000803e3d6000fd5b505050506040513d602081101561170357600080fd5b505190505b919050565b8061171781613f04565b60026000838152601a6020526040902060060154600160a01b900460ff16600381111561174057fe5b1461177f576040805162461bcd60e51b815260206004820152600a602482015269139bdd081a985a5b195960b21b604482015290519081900360640190fd5b6000828152601a6020526040902060030154156117d7576040805162461bcd60e51b8152602060048201526011602482015270416c726561647920756e7374616b696e6760781b604482015290519081900360640190fd5b6009546000838152601a6020526040902060040154811015611839576040805162461bcd60e51b8152602060048201526016602482015275125b98dbdb5c1b195d19481a985a5b081c195c9a5bd960521b604482015290519081900360640190fd5b6000838152601a6020526040902054600c5481101561185757600080fd5b6000848152601a60205260409020600601546001600160a01b031680156118cc57806001600160a01b031663a69df4b56040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156118b357600080fd5b505af11580156118c7573d6000803e3d6000fd5b505050505b6000858152601a60205260409020600a01546118fc906118f390849063ffffffff613f8e16565b60016000613fa0565b6000858152601a602052604080822060068101805460ff60a01b1916600160a01b1790556005908101549054825163f92ec5af60e01b8152600481018a90526001600160a01b039283166024820181905293519394929091169263f92ec5af9260448084019391929182900301818387803b15801561197a57600080fd5b505af115801561198e573d6000803e3d6000fd5b50505050505050505050565b60175481565b6007546001600160a01b031681565b6119b7613e97565b600955565b6119c4613e97565b6001600160a01b0381166119d757600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60268181548110611a0657fe5b6000918252602090912001546001600160a01b0316905081565b600e5481565b601e602052600090815260409020805460019091015482565b6000818152601a6020526040812060068101548154600390920154600954611a7493600160a01b90930460ff1692919061405c565b92915050565b611a82614094565b82611a8c81613f04565b6000848152601a602052604090206003015415611adf576040805162461bcd60e51b815260206004820152600c60248201526b4e6f2072657374616b696e6760a01b604482015290519081900360640190fd5b8215611af057611af03330856140d5565b611af9846141a7565b8115611b4c576000848152601a60205260409020600190810154611b359190611b2990869063ffffffff613f8e16565b9063ffffffff6141b616565b6000858152601a6020526040902060019081015592505b601154600090611b62908563ffffffff613f8e16565b60118190556000868152601a6020526040902054909150611b89908563ffffffff613f8e16565b6000868152601a6020526040812091909155611ba790859080613fa0565b6005546040805163532e19a960e01b81526004810188905290516001600160a01b039092169163532e19a99160248082019260009290919082900301818387803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b50506005546000888152601a6020526040808220548151631585a9f360e21b8152600481018c905260248101919091526044810187905290516001600160a01b039093169450635616a7cc93506064808201939182900301818387803b158015611c7157600080fd5b505af1158015611c85573d6000803e3d6000fd5b505050505050505050565b611c98612cfe565b611ca157600080fd5b8051611cb4906026906020840190615c9c565b5050565b80611cc281613f04565b600082815260208052604090205415611cda57600080fd5b6000828152601a602052604090206006810154600290910154600160a01b90910460ff169015801590611d1c57506000838152601a6020526040902060030154155b8015611d4857506001816003811115611d3157fe5b1480611d4857506002816003811115611d4657fe5b145b611d5157600080fd5b600954600090611d6890600163ffffffff613f8e16565b9050611d7484826141cb565b50505050565b6002546000906001600160a01b03163314611d9457600080fd5b600954601d546000908190611da7615d01565b6026546040805191840180835260208082028401019091528015611dd5578160200160208202803883390190505b5060408083019190915260268054825160208083028201810190945281815292830182828015611e2e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611e10575b50505050506060820152600060208201526026546080820152611e4f615d30565b6026546040805191850180835260208082028401019091528015611e7d578160200160208202803883390190505b50602082015260005b8881101561204c576000611ed48e8c8c85818110611ea057fe5b905060600201600380602002604051908101604052809291908260036020028082843760009201919091525061434f915050565b9050856001600160a01b0316816001600160a01b03161415611ef65750612044565b856001600160a01b0316816001600160a01b03161015611f16575061204c565b6001600160a01b0381166000908152601b6020908152604080832054808452601a909252909120805460068201546003909201548087529091600160a01b900460ff1690611f6890829084908e61405c565b15611ff3576000838152601a60205260409020600a01549398508893611fa7908390611f9b908d9063ffffffff613f8e16565b9063ffffffff613f8e16565b8651909a5015611fe157828660200151876040015181518110611fc657fe5b60209081029190910101526040860180516001019052611fee565b611feb8785614452565b96505b61203f565b600281600381111561200157fe5b141561203f5782876040015188600001518151811061201c57fe5b602090810291909101810191909152875160019081018952908801805190910190525b505050505b600101611e86565b50612058826000614452565b915061207a8d8b878e866040015187600001518760200151886040015161452f565b9d9c50505050505050505050505050565b6006546001600160a01b031681565b60165481565b601a60205260009081526040902080546001820154600283015460038401546004850154600586015460068701546007880154600889015460098a0154600a8b0154600b909b0154999a98999798969795966001600160a01b039586169695851695600160a01b90950460ff16948d565b601b6020526000908152604090205481565b60008061212f83614697565b6000858152601a602052604090206009015490925061215c9150600190611b29908463ffffffff613f8e16565b9392505050565b600c5481565b60295481565b612177613e97565b6000848152601a60205260409020600601546001600160a01b03168061219c57600080fd5b6040805163abf59fc960e01b81526001600160a01b03868116600483015285811660248301526044820185905291519183169163abf59fc99160648082019260009290919082900301818387803b158015611c7157600080fd5b60006001600160a01b03821615806122845750600654604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b15801561225657600080fd5b505afa15801561226a573d6000803e3d6000fd5b505050506040513d602081101561228057600080fd5b5051155b1561229157506000611708565b60065460408051632f745c5960e01b81526001600160a01b0385811660048301526000602483018190529251601a949190911691632f745c59916044808301926020929190829003018186803b1580156122ea57600080fd5b505afa1580156122fe573d6000803e3d6000fd5b505050506040513d602081101561231457600080fd5b5051815260208101919091526040016000205492915050565b600f5481565b60105481565b612341614094565b60105461234c612c89565b1061238e576040805162461bcd60e51b815260206004820152600d60248201526c6e6f206d6f726520736c6f747360981b604482015290519081900360640190fd5b600c548410156123da576040805162461bcd60e51b81526020600482015260126024820152711b9bdd08195b9bdd59da0819195c1bdcda5d60721b604482015290519081900360640190fd5b6123e685338587614713565b6123f2858584846147fd565b505050505050565b33301461243c576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6124498788886000614713565b612455856009546141cb565b600061249988868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506147fd92505050565b6005546040805163e12ab1af60e01b815260048101849052602481018a90526044810189905290519293506001600160a01b039091169163e12ab1af9160648082019260009290919082900301818387803b1580156124f757600080fd5b505af115801561250b573d6000803e3d6000fd5b505050505050505050505050565b60208080526000918252604091829020805460018083015460028085015460038601805489516101009682161596909602600019011692909204601f8101889004880285018801909852878452939691956001600160a01b03851695600160a01b90950460ff16949392908301828280156125d55780601f106125aa576101008083540402835291602001916125d5565b820191906000526020600020905b8154815290600101906020018083116125b857829003601f168201915b5050505050905085565b60195460ff1681565b60125481565b6000908152601a60205260409020600601546001600160a01b031690565b60005461010090046001600160a01b031681565b6004546001600160a01b03165b90565b6004805460408051631ab0168360e31b8152905160009333936001600160a01b03169263d580b4189281830192602092829003018186803b15801561267457600080fd5b505afa158015612688573d6000803e3d6000fd5b505050506040513d602081101561269e57600080fd5b50516001600160a01b0316146126ef576040805162461bcd60e51b81526020600482015260116024820152702737ba1039b630b9b41036b0b730b3b2b960791b604482015290519081900360640190fd5b606061273861273385858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250614c0a92505050565b614c2f565b90506000806000805b845181101561292557606061276886838151811061275b57fe5b6020026020010151614c2f565b905060006127898260008151811061277c57fe5b6020026020010151614d00565b9050612794816141a7565b60006127a68360018151811061277c57fe5b90506127b8858263ffffffff613f8e16565b6000838152601a60205260409020600601549095506001600160a01b03168015612886576000838152601a602090815260408083208054600a9091015482516306cbb60560e41b8152600481019290925260248201526044810186905290516001600160a01b03851692636cbb6050926064808201939182900301818787803b15801561284457600080fd5b505af1158015612858573d6000803e3d6000fd5b505050506040513d602081101561286e57600080fd5b50519050612882838263ffffffff6141b616565b9250505b6000838152601a60205260408120546128a5908463ffffffff6141b616565b6000858152601a602052604090208190559050806128ce576128c9846009546141cb565b612914565b6128eb856002815181106128de57fe5b6020026020010151614d60565b156129145761290b6128fe856001614d94565b899063ffffffff613f8e16565b60019099019897505b505060019093019250612741915050565b612946612938838563ffffffff613f8e16565b600003856000036000613fa0565b509695505050505050565b612959613e97565b60255460408051602481018690526044810185905260648082018590528251808303909101815260849091019091526020810180516001600160e01b0316633064689160e11b1790526129b5916001600160a01b031690614ede565b505050565b600654604080516331a9108f60e11b81526004810184905290516000926001600160a01b031691636352211e916024808301926020929190829003018186803b1580156116d957600080fd5b612a0e614094565b611cb48233836000614713565b601754604080513360208083019190915281830187905282518083038401815260609092019092528051910120612a5a9184908463ffffffff614f0616565b612a9d576040805162461bcd60e51b815260206004820152600f60248201526e2bb937b7339030b1b190383937b7b360891b604482015290519081900360640190fd5b336000908152601f6020526040812054612abe90859063ffffffff6141b616565b9050612aca338261505c565b336000818152601f60205260409020859055611d7490826150db565b600083612af2816151a0565b600354604080516323b872dd60e01b81526001600160a01b03868116600483015230602483015260448201889052915191909216916323b872dd9160648083019260209291908290030181600087803b158015612b4e57600080fd5b505af1158015612b62573d6000803e3d6000fd5b505050506040513d6020811015612b7857600080fd5b505195945050505050565b600a5481565b612b91612cfe565b612b9a57600080fd5b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b60095481565b60185481565b601f6020526000908152604090205481565b6004546001600160a01b031681565b602a5481565b600b5481565b600081612c29816151a0565b612c32836141a7565b6000838152601a6020526040812060090154612c5590600163ffffffff6141b616565b6000858152601a60205260409020600160099091015592505050919050565b6000908152601a60205260409020600a015490565b601d5490565b60115481565b81612c9f816151a0565b6000838152601a60205260409020600a0154612cc1908363ffffffff6141b616565b6000938452601a6020526040909320600a01929092555050565b60235461010090046001600160a01b031681565b6001546001600160a01b031690565b604080517f6d617469632e6e6574776f726b2e70726f78792e6f776e6572000000000000008152905190819003601901902054336001600160a01b039091161490565b60095490565b612d4f613e97565b612d5b816009546141cb565b50565b60275481565b80612d6e81613f04565b612d77826141a7565b611cb4823361520e565b6002546001600160a01b031681565b612d98614094565b602554604080516024810185905260448101849052306064808301919091528251808303909101815260849091019091526020810180516001600160e01b031663561ad5c960e11b179052611cb4916001600160a01b031690614ede565b60225481565b612e04613e97565b6005546016546040805163a3b1d8cb60e01b8152600481018590526024810192909252516001600160a01b039092169163a3b1d8cb9160448082019260009290919082900301818387803b158015612e5b57600080fd5b505af1158015612e6f573d6000803e3d6000fd5b505050506064811115612eb3576040805162461bcd60e51b8152602060048201526007602482015266746f6f2062696760c81b604482015290519081900360640190fd5b601655565b612ec0612cfe565b612ec957600080fd5b602554604080516024810185905260448082018590528251808303909101815260649091019091526020810180516001600160e01b0316639ddbbf8560e01b179052611cb4916001600160a01b031690614ede565b81612f28816151a0565b6000821315612f815760195460ff16612f81576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b6000838152601a602052604090206003015480612fa957612fa483600080613fa0565b612fec565b600954811115612fec576040805162461bcd60e51b8152602060048201526009602482015268756e7374616b696e6760b81b604482015290519081900360640190fd5b6000831261300357612ffe84846152cf565b611d74565b611d74848460001902612c95565b613019613e97565b8061302357600080fd5b600e55565b601c5490565b613036614094565b6025546040516024810187815260448201879052851515606483015260806084830190815260a483018590526130df936001600160a01b03169263a685487760e01b928a928a928a928a928a9260c40184848082843760008184015260408051601f19601f9093018316909401848103909201845252506020810180516001600160e01b03199a909a166001600160e01b03909a169990991790985250614ede95505050505050565b5050505050565b6130ee613e97565b6130f661530a565b565b60085490565b60245481565b61310c613e97565b611cb482826150db565b61311e613e97565b600c91909155600d55565b6000818152601a6020526040812060030154819061314e5761314a83614697565b5090505b6000838152601a6020526040902060019081015461215c9190611b29908463ffffffff613f8e16565b6000838152601a60205260408120600601546001600160a01b031633148061321657506004805460408051631ab0168360e31b8152905133936001600160a01b039093169263d580b41892808201926020929091829003018186803b1580156131df57600080fd5b505afa1580156131f3573d6000803e3d6000fd5b505050506040513d602081101561320957600080fd5b50516001600160a01b0316145b613255576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6003546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018790529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156132ab57600080fd5b505af11580156132bf573d6000803e3d6000fd5b505050506040513d60208110156132d557600080fd5b5051949350505050565b6132e7613e97565b306001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561332a57600080fd5b505afa15801561333e573d6000803e3d6000fd5b505050506040513d602081101561335457600080fd5b50516001600160a01b03161461336957600080fd5b6000918252601a602052604090912060060180546001600160a01b0319166001600160a01b03909216919091179055565b6133a2613e97565b806133ac57600080fd5b600554600b5460408051632dbe9d3160e21b8152600481018590526024810192909252516001600160a01b039092169163b6fa74c49160448082019260009290919082900301818387803b15801561340357600080fd5b505af1158015613417573d6000803e3d6000fd5b505050600b9190915550565b60145481565b60005460ff1681565b336000908152601b6020908152604080832054808452601a9092529091206006810154815460039092015460095461347793600160a01b90930460ff1692919061405c565b6134b8576040805162461bcd60e51b815260206004820152600d60248201526c3737ba103b30b634b230ba37b960991b604482015290519081900360640190fd5b6000818152601a60205260409020600601546001600160a01b03168061351e576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b604080516303dd464160e51b8152841515600482015290516001600160a01b03831691637ba8c82091602480830192600092919082900301818387803b15801561356757600080fd5b505af115801561357b573d6000803e3d6000fd5b50505050505050565b60216020526000908152604090205481565b806135a081613f04565b6000828152601a602052604090206003015480158015906135d657506009546008546135d390839063ffffffff613f8e16565b11155b8015613609575060036000848152601a6020526040902060060154600160a01b900460ff16600381111561360657fe5b14155b61361257600080fd5b6000838152601a6020526040812054601154909190613637908363ffffffff6141b616565b60118190559050613648853361520e565b60065460408051630852cd8d60e31b81526004810188905290516001600160a01b03909216916342966c689160248082019260009290919082900301818387803b15801561369557600080fd5b505af11580156136a9573d6000803e3d6000fd5b5050506000868152601a6020526040812081815560048101919091556005810180546001600160a01b03191690556000197f584f46c60af19681376031579adb04a2416e54ee5505351c2a8435e3766026ea55600601805460ff60a01b1916600360a01b1790555061371b33836150db565b6005546040805163ae2e26b160e01b815233600482015260248101889052604481018590526064810184905290516001600160a01b039092169163ae2e26b19160848082019260009290919082900301818387803b158015611c7157600080fd5b8161378681613f04565b61378f836141a7565b602554604080516024810186905260448082018690528251808303909101815260649091019091526020810180516001600160e01b0316636e6cb15960e11b1790526129b5916001600160a01b031690614ede565b60285481565b601c54601d5482565b6137fb613e97565b6000811161380857600080fd5b600554600a5460408051635071805360e11b8152600481018590526024810192909252516001600160a01b039092169163a0e300a69160448082019260009290919082900301818387803b15801561385f57600080fd5b505af1158015613873573d6000803e3d6000fd5b505050600a82905550600881905561389281600463ffffffff61531616565b60158190556009546138a99163ffffffff613f8e16565b60185550565b6138b7612cfe565b6138c057600080fd5b6001600160a01b0381166138d357600080fd5b6002546040516001600160a01b038084169216907f211c9015fc81c0dbd45bd99f0f29fc1c143bfd53442d5ffd722bbbef7a887fe990600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000908152601a602052604090205490565b6005546001600160a01b031681565b613958613e97565b6019805460ff1916911515919091179055565b613973612cfe565b61397c57600080fd5b612d5b81615338565b8161398f81613f04565b600061399a836153a7565b600954600f5460008781526021602052604090205492935090916139c39163ffffffff613f8e16565b811015613a05576040805162461bcd60e51b815260206004820152600b60248201526a139bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6000858152601a602090815260408083206005908101549054915163b80fbce560e01b8152600481018a81526001600160a01b039283166024830181905288841660448401526080606484019081528b5160848501528b519197949095169563b80fbce5958d9589958c958f95909460a490920192918601918190849084905b83811015613a9d578181015183820152602001613a85565b50505050905090810190601f168015613aca5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015613aec57600080fd5b505af1158015613b00573d6000803e3d6000fd5b5050506000878152601a602052604090206003015415159050613b2f57613b2681615460565b613b2f8361556a565b6001600160a01b039081166000908152601b60209081526040808320600019905594909216808252848220889055968152601a825283812060050180546001600160a01b031916909717909655602190529320929092555050565b60235460ff1615613bd3576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6023805460ff19166001179055613be981613ee5565b613c33576040805162461bcd60e51b8152602060048201526016602482015275185d58dd1a5bdb881a5b5c1b081a5b98dbdc9c9958dd60521b604482015290519081900360640190fd5b602580546001600160a01b03199081166001600160a01b038481169190911790925560008054610100600160a81b031916610100878516021790556004805482168c84161790556002805482168b84161790556003805482168a841617905560068054821689841617905560058054821688841617905560078054909116918616919091179055613cc382615338565b5050612000600855505060016009819055610376600a90815569044664c7bf6451f00000600b55670de0b6b3a7640000600c819055600d55610400600e556064600f55600760105560128290556108006015556016556019805460ff191690911790555050505050565b613d35613e97565b6009546138a9908263ffffffff613f8e16565b613d50613e97565b6130f6615684565b6025546001600160a01b031681565b60078211613db0576040805162461bcd60e51b815260206004820152601160248201527024b73b30b634b21036b4b3b930ba34b7b760791b604482015290519081900360640190fd5b6000838152601a6020526040808220600601548151636e7ce59160e01b81523360048201526024810185905291516001600160a01b0390911692636e7ce591926044808201939182900301818387803b158015613e0c57600080fd5b505af1158015613e20573d6000803e3d6000fd5b5050506000838152601a6020526040808220600601548151632830728d60e21b81523360048201526024810186905291516001600160a01b03909116935063a0c1ca349260448084019391929182900301818387803b15801561356757600080fd5b600d5481565b6003546001600160a01b031681565b60005461010090046001600160a01b031633146130f65760405162461bcd60e51b8152600401808060200182810382526026815260200180615dce6026913960400191505060405180910390fd5b60006001600160a01b038216613efd57506000611708565b503b151590565b600654604080516331a9108f60e11b815260048101849052905133926001600160a01b031691636352211e916024808301926020929190829003018186803b158015613f4f57600080fd5b505afa158015613f63573d6000803e3d6000fd5b505050506040513d6020811015613f7957600080fd5b50516001600160a01b031614612d5b57600080fd5b60008282018381101561215c57600080fd5b8061403a576000831315613fc957601c54613fc1908463ffffffff613f8e16565b601c55613fed565b6000831215613fed57601c54613fe990600085900363ffffffff6141b616565b601c555b600082131561401157601d54614009908363ffffffff613f8e16565b601d55614035565b600082121561403557601d5461403190600084900363ffffffff6141b616565b601d555b6129b5565b6000818152601e60205260409020805484018155600101805483019055505050565b60008084118015614074575082158061407457508183115b801561408b5750600185600381111561408957fe5b145b95945050505050565b60005460ff16156130f6576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b600354604080516323b872dd60e01b81526001600160a01b038681166004830152858116602483015260448201859052915191909216916323b872dd9160648083019260209291908290030181600087803b15801561413357600080fd5b505af1158015614147573d6000803e3d6000fd5b505050506040513d602081101561415d57600080fd5b50516129b5576040805162461bcd60e51b81526020600482015260146024820152731d1c985b9cd9995c88199c9bdb4819985a5b195960621b604482015290519081900360640190fd5b612d5b81602454602454615693565b6000828211156141c557600080fd5b50900390565b6141d4826141a7565b6000828152601a6020526040812054906141ed846129ba565b6000858152601a6020526040902060038101859055600a810154600690910154919250906001600160a01b0316801561427457806001600160a01b031663f83d08ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561425b57600080fd5b505af115801561426f573d6000803e3d6000fd5b505050505b6000868152601a6020526040902060050154614298906001600160a01b0316615460565b6142a2868461520e565b60006009548611156142b457856142b7565b60005b90506142cb83860160000360001983613fa0565b60055460408051635e04d48360e01b81526001600160a01b038781166004830152602482018b9052604482018a90526064820189905291519190921691635e04d48391608480830192600092919082900301818387803b15801561432e57600080fd5b505af1158015614342573d6000803e3d6000fd5b5050505050505050505050565b805160208201516040830151600092919060ff167f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156143975760009350505050611a74565b601b8160ff1610156143a757601b015b8060ff16601b141580156143bf57508060ff16601c14155b156143d05760009350505050611a74565b60408051600080825260208083018085528a905260ff85168385015260608301879052608083018690529251909260019260a080820193601f1981019281900390910190855afa158015614428573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661444857600080fd5b9695505050505050565b61445a615d01565b8260800151836020015110801561449e5750816001600160a01b0316836060015184602001518151811061448a57fe5b60200260200101516001600160a01b031614155b1561451f57601b600084606001518560200151815181106144bb57fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205483604001518460000151815181106144f857fe5b6020908102919091018101919091528351600190810185529084018051909101905261445a565b5050602081018051600101905290565b601c5460009061455c6001611f9b600361455085600263ffffffff61573416565b9063ffffffff61531616565b8810156145a6576040805162461bcd60e51b8152602060048201526013602482015272322f332b31206e6f6e2d6d616a6f726974792160681b604482015290519081900360640190fd5b60006145b38b8a8461575b565b905060006145d160646145506016548561573490919063ffffffff16565b6001600160a01b038c166000908152601b6020908152604080832054808452601a90925290912060018101549293509091614612908463ffffffff613f8e16565b600182015560178b9055600061465f6146508e6145506a084595161401484a0000006146448a8a63ffffffff6141b616565b9063ffffffff61573416565b6024549063ffffffff613f8e16565b905061466c8b8b836158af565b602481905561467c8989836158af565b6146846158e3565b50929d9c50505050505050505050505050565b6000818152601a602052604081208054600a9091015482919082906146c390839063ffffffff613f8e16565b6000868152601a60205260409020600b0154602454919250900361470786846147016a084595161401484a000000614550868863ffffffff61573416565b85615958565b94509450505050915091565b600d5482101561475a576040805162461bcd60e51b815260206004820152600d60248201526c199959481d1bdbc81cdb585b1b609a1b604482015290519081900360640190fd5b614774833061476f858563ffffffff613f8e16565b6140d5565b602254614787908363ffffffff613f8e16565b6022556005546040805163a449d79560e01b81526001600160a01b038781166004830152602482018690529151919092169163a449d79591604480830192600092919082900301818387803b1580156147df57600080fd5b505af11580156147f3573d6000803e3d6000fd5b5050505050505050565b600080614809836153a7565b600954601254600554601154939450919290916001600160a01b031690600090614839908a63ffffffff613f8e16565b905080601181905550604051806101a001604052808a8152602001600181526020018581526020016000815260200160008152602001866001600160a01b031681526020018961488a576000614916565b600754600480546040805163d4ad267360e01b81529283018990526001600160a01b03888116602485015291821660448401525192169163d4ad2673916064808201926020929091908290030181600087803b1580156148e957600080fd5b505af11580156148fd573d6000803e3d6000fd5b505050506040513d602081101561491357600080fd5b50515b6001600160a01b031681526020016001815260006020808301829052604080840183905260016060808601829052608080870186905260245460a0978801528a8652601a855294839020875181559387015191840191909155908501516002830155840151600380830191909155918401516004820155918301516005830180546001600160a01b039283166001600160a01b03199182161790915560c08501516006850180549190931691161780825560e08501519260ff60a01b1990911690600160a01b9084908111156149e857fe5b0217905550610100820151600782015561012082015160088201556101408201516009820155610160820151600a82015561018090910151600b9091015560008381526021602052604080822086905560065481516340c10f1960e01b81526001600160a01b038e8116600483015260248201889052925192909116926340c10f199260448084019382900301818387803b158015614a8657600080fd5b505af1158015614a9a573d6000803e3d6000fd5b5050506001600160a01b0386166000908152601b60205260408120859055614ac791508a90600190613fa0565b836020600085815260200190815260200160002060010181905550816001600160a01b03166333a8383c868986888e876040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b0316815260200180602001868152602001858152602001848152602001838152602001828103825287818151815260200191508051906020019080838360005b83811015614b73578181015183820152602001614b5b565b50505050905090810190601f168015614ba05780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b158015614bc457600080fd5b505af1158015614bd8573d6000803e3d6000fd5b50505050614bf0600184613f8e90919063ffffffff16565b601255614bfc8561556a565b509098975050505050505050565b614c12615d51565b506040805180820190915281518152602082810190820152919050565b6060614c3a826159ec565b614c4357600080fd5b6000614c4e83615a26565b9050606081604051908082528060200260200182016040528015614c8c57816020015b614c79615d51565b815260200190600190039081614c715790505b5090506000614c9e8560200151615a82565b60208601510190506000805b84811015614cf557614cbb83615ae5565b9150604051806040016040528083815260200184815250848281518110614cde57fe5b602090810291909101015291810191600101614caa565b509195945050505050565b805160009015801590614d1557508151602110155b614d1e57600080fd5b6000614d2d8360200151615a82565b83516020808601518301805193945091849003929190831015614d5757826020036101000a820491505b50949350505050565b8051600090600114614d7157600080fd5b6020820151805160001a908115614d89576001614d8c565b60005b949350505050565b6000828152601a60205260408120600601546001600160a01b03168015614e0957806001600160a01b031663f83d08ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015614df057600080fd5b505af1158015614e04573d6000803e3d6000fd5b505050505b600954614e1c818563ffffffff613f8e16565b6000868152601a602052604080822060048082019490945560068101805460ff60a01b1916600160a11b1790556005805491015482516381dc101b60e01b81529485018a9052602485018690526001600160a01b03908116604486015291519116926381dc101b92606480830193919282900301818387803b158015614ea157600080fd5b505af1158015614eb5573d6000803e3d6000fd5b5050506000868152601a60205260409020600a810154905461408b92509063ffffffff613f8e16565b600080825160208401856127105a03f43d604051816000823e828015614f02578282f35b8282fd5b60006020825181614f1357fe5b0615614f5d576040805162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840e0e4dedecc40d8cadccee8d60631b604482015290519081900360640190fd5b60006020835181614f6a57fe5b0490508060020a8510614fbc576040805162461bcd60e51b81526020600482015260156024820152744c65616620696e64657820697320746f6f2062696760581b604482015290519081900360640190fd5b60008660205b8551811161504e578581015192506002880661500e5781836040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209150615040565b828260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091505b600288049750602001614fc2565b509094149695505050505050565b60225461506f908263ffffffff6141b616565b6022556005546040805163122b648160e01b81526001600160a01b038581166004830152602482018590529151919092169163122b648191604480830192600092919082900301818387803b1580156150c757600080fd5b505af11580156123f2573d6000803e3d6000fd5b6003546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561513157600080fd5b505af1158015615145573d6000803e3d6000fd5b505050506040513d602081101561515b57600080fd5b5051611cb4576040805162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b6000818152601a60205260409020600601546001600160a01b03163314612d5b576040805162461bcd60e51b815260206004820152601860248201527f496e76616c696420636f6e747261637420616464726573730000000000000000604482015290519081900360640190fd5b6000828152601a602052604081206001908101546152319163ffffffff6141b616565b601454909150615247908263ffffffff613f8e16565b6014556000838152601a60205260409020600181810155602454600b9091015561527182826150db565b60055460145460408051635b42d93560e11b815260048101879052602481018590526044810192909252516001600160a01b039092169163b685b26a9160648082019260009290919082900301818387803b15801561356757600080fd5b6000828152601a60205260409020600a01546152f1908263ffffffff613f8e16565b6000928352601a6020526040909220600a019190915550565b6000805460ff19169055565b600080821161532457600080fd5b600082848161532f57fe5b04949350505050565b6001600160a01b03811661534b57600080fd5b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b600081516040146153e9576040805162461bcd60e51b81526020600482015260076024820152663737ba10383ab160c91b604482015290519081900360640190fd5b815160208301206001600160a01b0381161580159061541e57506001600160a01b0381166000908152601b6020526040902054155b611a74576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b604482015290519081900360640190fd5b6026805490600090600019830183811061547657fe5b600091825260209091200154602680546001600160a01b0390921692509060001984019081106154a257fe5b600091825260209091200180546001600160a01b031916905560001982015b801561555957836001600160a01b0316826001600160a01b031614156154e657615559565b602660018203815481106154f657fe5b9060005260206000200160009054906101000a90046001600160a01b0316826026600184038154811061552557fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790559150600019016154c1565b506000198201611d74602682615d6b565b6026805460018101825560008290527f744a2cf8fd7008e3d53b67916e73460df9fa5214e3ef23dd4259ca09493a35940180546001600160a01b0319166001600160a01b0384161790555460001901805b801561563c576000602660018303815481106155d357fe5b6000918252602090912001546001600160a01b03908116915084168110156155fb575061563c565b806026838154811061560957fe5b600091825260209091200180546001600160a01b0319166001600160a01b039290921691909117905550600019016155bb565b8181146129b557826026828154811061565157fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6000805460ff19166001179055565b6000838152601a60205260409020600b015482811015615712576000848152601a602052604090208054600a9091015480156156fa5760006156db838363ffffffff613f8e16565b90506156f48784846156ef8b868c8b615b7e565b615ba2565b5061570f565b61570f8661570a88858988615b7e565b615c48565b50505b80821115611d74576000848152601a60205260409020600b0182905550505050565b60008261574357506000611a74565b8282028284828161575057fe5b041461215c57600080fd5b600e54600b54600091908261577b83888161577257fe5b04602954615c86565b905060008111801561578f57506027548114155b156157d057602754156157ca5760006064602a548402816157ac57fe5b0490508160275411156157c257918201916157c8565b80830392505b505b60278190555b6000838811156158695760285461581861580860646145506157fb6002600019890189020486615734565b889063ffffffff61573416565b611b29868663ffffffff61573416565b915061583a61582d848763ffffffff61573416565b8a9063ffffffff6141b616565b9850615865615858606461455084614644898963ffffffff61573416565b859063ffffffff6141b616565b9350505b61588d615880856145508b8763ffffffff61573416565b829063ffffffff613f8e16565b90506158a386614550838a63ffffffff61573416565b98975050505050505050565b60245460005b838110156130df576158db8582815181106158cc57fe5b60200260200101518385615693565b6001016158b5565b60095460006158f982600163ffffffff613f8e16565b9050615903615d51565b506000818152601e6020908152604080832081518083019092528054808352600190910154928201839052909261593a9290613fa0565b506000918252601e6020526040822082815560010191909155600955565b6000808261596b575060009050806159e3565b600061598184614550888863ffffffff61573416565b6000888152601a602052604090206007015490915080156159c8576159c56159b86064614550846146448b8863ffffffff6141b616565b839063ffffffff613f8e16565b91505b60006159da878463ffffffff6141b616565b92945091925050505b94509492505050565b80516000906159fd57506000611708565b6020820151805160001a9060c0821015615a1c57600092505050611708565b5060019392505050565b8051600090615a3757506000611708565b60008090506000615a4b8460200151615a82565b602085015185519181019250015b80821015615a7957615a6a82615ae5565b60019093019290910190615a59565b50909392505050565b8051600090811a6080811015615a9c576000915050611708565b60b8811080615ab7575060c08110801590615ab7575060f881105b15615ac6576001915050611708565b60c0811015615ada5760b519019050611708565b60f519019050611708565b80516000908190811a6080811015615b005760019150615b77565b60b8811015615b1557607e1981019150615b77565b60c0811015615b425760b78103600185019450806020036101000a85510460018201810193505050615b77565b60f8811015615b575760be1981019150615b77565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60008183036144486a084595161401484a000000614550838863ffffffff61573416565b6000615bb4838563ffffffff613f8e16565b9050600080615bc587878686615958565b90925090508015615c05576000878152601a6020526040902060090154615bf2908263ffffffff613f8e16565b6000888152601a60205260409020600901555b811561357b576000878152601a6020526040902060010154615c2d908363ffffffff613f8e16565b6000888152601a602052604090206001015550505050505050565b8015611cb4576000828152601a6020526040902060010154615c70908263ffffffff613f8e16565b6000838152601a60205260409020600101555050565b6000818310615c95578161215c565b5090919050565b828054828255906000526020600020908101928215615cf1579160200282015b82811115615cf157825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615cbc565b50615cfd929150615d8f565b5090565b6040518060a0016040528060008152602001600081526020016060815260200160608152602001600081525090565b60405180606001604052806000815260200160608152602001600081525090565b604051806040016040528060008152602001600081525090565b8154818355818111156129b5576000838152602090206129b5918101908301615db3565b61262d91905b80821115615cfd5780546001600160a01b0319168155600101615d95565b61262d91905b80821115615cfd5760008155600101615db956fe4f6e6c7920676f7665726e616e636520636f6e747261637420697320617574686f72697a6564a265627a7a7231582058be6eb435b22b31280540e2326580f39ea0fe929cd1983b8a5ad5d82a779e6764736f6c63430005110032
Deployed Bytecode Sourcemap
132244:45525:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;132244:45525:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;141242:116;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;141242:116:0;;:::i;:::-;;142089:497;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;142089:497:0;;;;;;;;;;;;;;;;;;;;;;;;:::i;122945:28::-;;;:::i;:::-;;;;;;;;;;;;;;;;122867:27;;;:::i;122324:31::-;;;:::i;138315:237::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;138315:237:0;;:::i;135882:134::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135882:134:0;-1:-1:-1;;;;;135882:134:0;;:::i;157932:1017::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;157932:1017:0;;:::i;123060:31::-;;;:::i;122267:50::-;;;:::i;:::-;;;;-1:-1:-1;;;;;122267:50:0;;;;;;;;;;;;;;137931:119;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137931:119:0;;:::i;138058:146::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;138058:146:0;-1:-1:-1;;;;;138058:146:0;;:::i;124073:24::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;124073:24:0;;:::i;122670:38::-;;;:::i;123449:60::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;123449:60:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;137252:324;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137252:324:0;;:::i;:::-;;;;;;;;;;;;;;;;;;148162:963;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;148162:963:0;;;;;;;;;;;;;;:::i;139921:104::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;139921:104:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;139921:104:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;139921:104:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;139921:104:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;139921:104:0;;-1:-1:-1;139921:104:0;;-1:-1:-1;;;;;139921:104:0:i;145275:538::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;145275:538:0;;:::i;152115:3184::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;152115:3184:0;;;;;;;;;;;;;-1:-1:-1;;;;;152115:3184:0;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;152115:3184:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;152115:3184:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;152115:3184:0;;-1:-1:-1;152115:3184:0;-1:-1:-1;152115:3184:0;:::i;122231:29::-;;;:::i;123000:28::-;;;:::i;123250:47::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;123250:47:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;123250:47:0;-1:-1:-1;;;;;123250:47:0;;;;;;-1:-1:-1;;;;;123250:47:0;-1:-1:-1;;;;;123250:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123304:52;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;123304:52:0;-1:-1:-1;;;;;123304:52:0;;:::i;136173:283::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;136173:283:0;;:::i;122566:25::-;;;:::i;124345:37::-;;;:::i;141554:389::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;141554:389:0;;;-1:-1:-1;;;;;141554:389:0;;;;;;;;;;;;;;;;;;;:::i;143409:262::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;143409:262:0;-1:-1:-1;;;;;143409:262:0;;:::i;122715:32::-;;;:::i;122756:33::-;;;:::i;146486:481::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;146486:481:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;146486:481:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;146486:481:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;146486:481:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;146486:481:0;;-1:-1:-1;146486:481:0;;-1:-1:-1;;;;;146486:481:0:i;144640:627::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;144640:627:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;144640:627:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;144640:627:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;144640:627:0;;-1:-1:-1;144640:627:0;-1:-1:-1;144640:627:0;:::i;123611:51::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;123611:51:0;;:::i;:::-;;;;;;;;;;;;;;;-1:-1:-1;;;;;123611:51:0;-1:-1:-1;;;;;123611:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;123611:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123212:29;;;:::i;122835:25::-;;;:::i;137098:146::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137098:146:0;;:::i;25204:29::-;;;:::i;135262:87::-;;;:::i;156101:1823::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;156101:1823:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;156101:1823:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;156101:1823:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;156101:1823:0;;-1:-1:-1;156101:1823:0;-1:-1:-1;156101:1823:0;:::i;138956:542::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;138956:542:0;;;;;;;;;;;;:::i;135417:118::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135417:118:0;;:::i;142638:150::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;142638:150:0;;;;;;;;:::i;142796:605::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;142796:605:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;142796:605:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;142796:605:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;142796:605:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;142796:605:0;;-1:-1:-1;142796:605:0;;-1:-1:-1;;;;;142796:605:0:i;146231:247::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;146231:247:0;;;;;;;;;;;-1:-1:-1;;;;;146231:247:0;;:::i;122450:22::-;;;:::i;47147:140::-;;;:::i;122377:27::-;;;:::i;123171:34::-;;;:::i;123518:46::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;123518:46:0;-1:-1:-1;;;;;123518:46:0;;:::i;122169:23::-;;;:::i;124466:36::-;;;:::i;122502:32::-;;;:::i;155739:354::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;155739:354:0;;:::i;136024:141::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;136024:141:0;;:::i;136847:117::-;;;:::i;122802:26::-;;;:::i;150862:226::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;150862:226:0;;;;;;;:::i;123971:24::-;;;:::i;46357:79::-;;;:::i;134950:255::-;;;:::i;135543:85::-;;;:::i;137802:121::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137802:121:0;;:::i;124156:32::-;;;:::i;149133:176::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;149133:176:0;;:::i;120196:24::-;;;:::i;144191:441::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;144191:441:0;;;;;;;:::i;123784:31::-;;;:::i;140964:270::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140964:270:0;;:::i;139543:370::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;139543:370:0;;;;;;;:::i;149777:870::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;149777:870:0;;;;;;;:::i;138560:162::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;138560:162:0;;:::i;136972:118::-;;;:::i;143679:504::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;143679:504:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;143679:504:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;143679:504:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;143679:504:0;;-1:-1:-1;143679:504:0;-1:-1:-1;143679:504:0;:::i;26348:73::-;;;:::i;135636:99::-;;;:::i;124002:29::-;;;:::i;141951:130::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;141951:130:0;;;;;;;;:::i;141366:180::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;141366:180:0;;;;;;;:::i;136464:375::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;136464:375:0;;:::i;145821:402::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;145821:402:0;;;;;;;;;;;-1:-1:-1;;;;;145821:402:0;;:::i;140126:270::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140126:270:0;;;;;;-1:-1:-1;;;;;140126:270:0;;:::i;138730:218::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;138730:218:0;;:::i;122901:37::-;;;:::i;25719:18::-;;;:::i;159915:641::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;159915:641:0;;;;:::i;123717:58::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;123717:58:0;;:::i;146975:1179::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;146975:1179:0;;:::i;155307:424::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;155307:424:0;;;;;;;:::i;124257:42::-;;;:::i;123415:27::-;;;:::i;140404:351::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140404:351:0;;:::i;120634:210::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;120634:210:0;-1:-1:-1;;;;;120634:210:0;;:::i;135743:131::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135743:131:0;;:::i;122199:25::-;;;:::i;137632:112::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137632:112:0;;;;:::i;47464:109::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;47464:109:0;-1:-1:-1;;;;;47464:109:0;;:::i;151096:1011::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;151096:1011:0;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;151096:1011:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;151096:1011:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;151096:1011:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;151096:1011:0;;-1:-1:-1;151096:1011:0;;-1:-1:-1;;;;;151096:1011:0:i;133548:1394::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;133548:1394:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;140813:143::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140813:143:0;;:::i;26271:69::-;;;:::i;124038:28::-;;;:::i;149317:452::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;149317:452:0;;;;;;;;;;;;:::i;122616:29::-;;;:::i;122143:19::-;;;:::i;141242:116::-;25383:19;:17;:19::i;:::-;141324:17;:26;141242:116::o;142089:497::-;25383:19;:17;:19::i;:::-;142299:26;142310:14;142299:10;:26::i;:::-;142291:35;;;;;;142337:9;:24;;-1:-1:-1;;;;;;142337:24:0;;;142372:13;:30;;-1:-1:-1;;;;;;142372:30:0;;;-1:-1:-1;;;;;142372:30:0;;;;;;;142413:11;:38;;;;;;;;;;;;;;142462:6;:36;;;;;;;;;;;;;;142509:21;:69;;;;;;;;;;142089:497::o;122945:28::-;;;;:::o;122867:27::-;;;;:::o;122324:31::-;;;;:::o;138315:237::-;25383:19;:17;:19::i;:::-;138412:17;138404:26;;;;;;138441:6;;138481:18;;138441:59;;;-1:-1:-1;;;138441:59:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;138441:6:0;;;;:25;;:59;;;;;:6;;:59;;;;;;;;:6;;:59;;;5:2:-1;;;;30:1;27;20:12;5:2;138441:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;138511:18:0;:33;;;;-1:-1:-1;138315:237:0:o;135882:134::-;135968:11;;:40;;;-1:-1:-1;;;135968:40:0;;-1:-1:-1;;;;;135968:40:0;;;;;;;135941:7;135968:40;;;;;;;;135941:7;;135968:11;;:31;;:40;;;;;;;;;;;;;;;:11;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;135968:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;135968:40:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135968:40:0;;-1:-1:-1;135882:134:0;;;;:::o;157932:1017::-;157987:11;132987:26;133001:11;132987:13;:26::i;:::-;158053:13;158019:23;;;;:10;:23;;;;;:30;;;-1:-1:-1;;;158019:30:0;;;;:47;;;;;;;;;158011:70;;;;;-1:-1:-1;;;158011:70:0;;;;;;;;;;;;-1:-1:-1;;;158011:70:0;;;;;;;;;;;;;;;158100:23;;;;:10;:23;;;;;:41;;;:46;158092:76;;;;;-1:-1:-1;;;158092:76:0;;;;;;;;;;;;-1:-1:-1;;;158092:76:0;;;;;;;;;;;;;;;158205:12;;158181:21;158236:23;;;:10;:23;;;;;:32;;;:49;-1:-1:-1;158236:49:0;158228:84;;;;;-1:-1:-1;;;158228:84:0;;;;;;;;;;;;-1:-1:-1;;;158228:84:0;;;;;;;;;;;;;;;158325:14;158342:23;;;:10;:23;;;;;:30;158401:10;;158391:20;;;158383:29;;;;;;158425:26;158454:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;158454:39:0;158508:34;;158504:111;;158575:18;-1:-1:-1;;;;;158559:42:0;;:44;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;158559:44:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;158559:44:0;;;;158504:111;158724:23;;;;:10;:23;;;;;:39;;;158691:81;;158713:51;;:6;;:51;:10;:51;:::i;:::-;158767:1;158770;158691:14;:81::i;:::-;158785:23;;;;:10;:23;;;;;;:30;;;:46;;-1:-1:-1;;;;158785:46:0;-1:-1:-1;;;158785:46:0;;;158861:30;;;;;158902:6;;:39;;-1:-1:-1;;;158902:39:0;;;;;;;;-1:-1:-1;;;;;158861:30:0;;;158902:39;;;;;;;;158861:30;;158902:6;;;;;:18;;:39;;;;;158785:23;;158902:39;;;;;;158785:23;158902:6;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;158902:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;158902:39:0;;;;133024:1;;;;157932:1017;;:::o;123060:31::-;;;;:::o;122267:50::-;;;-1:-1:-1;;;;;122267:50:0;;:::o;137931:119::-;25383:19;:17;:19::i;:::-;138014:12;:28;137931:119::o;138058:146::-;25383:19;:17;:19::i;:::-;-1:-1:-1;;;;;138140:22:0;;138132:31;;;;;;138174:5;:22;;-1:-1:-1;;;;;;138174:22:0;-1:-1:-1;;;;;138174:22:0;;;;;;;;;;138058:146::o;124073:24::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;124073:24:0;;-1:-1:-1;124073:24:0;:::o;122670:38::-;;;;:::o;123449:60::-;;;;;;;;;;;;;;;;;;;:::o;137252:324::-;137315:4;137383:23;;;:10;:23;;;;;:30;;;;137432;;137481:41;;;;;137541:12;;137352:216;;-1:-1:-1;;;137383:30:0;;;;;;137432;137481:41;137352:12;:216::i;:::-;137332:236;137252:324;-1:-1:-1;;137252:324:0:o;148162:963::-;25785:17;:15;:17::i;:::-;148304:11;132987:26;133001:11;132987:13;:26::i;:::-;148336:23;;;;:10;:23;;;;;:41;;;:46;148328:71;;;;;-1:-1:-1;;;148328:71:0;;;;;;;;;;;;-1:-1:-1;;;148328:71:0;;;;;;;;;;;;;;;148416:10;;148412:96;;148443:53;148462:10;148482:4;148489:6;148443:18;:53::i;:::-;148520:27;148535:11;148520:14;:27::i;:::-;148564:12;148560:186;;;148613:23;;;;:10;:23;;;;;122133:1;148613:30;;;;148602:66;;122133:1;148602:42;;:6;;:42;:10;:42;:::i;:::-;:46;:66;:46;:66;:::i;:::-;148683:23;;;;:10;:23;;;;;122133:1;148683:30;;;:51;148593:75;-1:-1:-1;148560:186:0;148783:11;;148758:22;;148783:23;;148799:6;148783:23;:15;:23;:::i;:::-;148817:11;:28;;;148889:23;;;;:10;:23;;;;;:30;148758:48;;-1:-1:-1;148889:42:0;;148924:6;148889:42;:34;:42;:::i;:::-;148856:23;;;;:10;:23;;;;;:75;;;;148944:36;;148966:6;;148856:23;148944:14;:36::i;:::-;148993:6;;:34;;;-1:-1:-1;;;148993:34:0;;;;;;;;;;-1:-1:-1;;;;;148993:6:0;;;;:21;;:34;;;;;:6;;:34;;;;;;;;:6;;:34;;;5:2:-1;;;;30:1;27;20:12;5:2;148993:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;149038:6:0;;;149070:23;;;:10;:23;;;;;;:30;149038:79;;-1:-1:-1;;;149038:79:0;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;149038:6:0;;;;-1:-1:-1;149038:18:0;;-1:-1:-1;149038:79:0;;;;;;;;;;;:6;;:79;;;5:2:-1;;;;30:1;27;20:12;5:2;149038:79:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;149038:79:0;;;;133024:1;25813;148162:963;;;:::o;139921:104::-;46569:9;:7;:9::i;:::-;46561:18;;;;;;139999;;;;:7;;:18;;;;;:::i;:::-;;139921:104;:::o;145275:538::-;145333:11;132987:26;133001:11;132987:13;:26::i;:::-;145365:29;;;;:16;:29;;;;;:36;:41;145357:50;;;;;;145420:13;145436:23;;;:10;:23;;;;;:30;;;;145499:39;;;;;-1:-1:-1;;;145436:30:0;;;;;;145499:43;;;;:110;;-1:-1:-1;145563:23:0;;;;:10;:23;;;;;:41;;;:46;145499:110;:183;;;;-1:-1:-1;145641:13:0;145631:6;:23;;;;;;;;;:50;;;-1:-1:-1;145668:13:0;145658:6;:23;;;;;;;;;145631:50;145477:216;;;;;;145726:12;;145706:17;;145726:19;;145743:1;145726:19;:16;:19;:::i;:::-;145706:39;;145773:32;145782:11;145795:9;145773:8;:32::i;:::-;133024:1;;145275:538;;:::o;152115:3184::-;120458:9;;152330:7;;-1:-1:-1;;;;;120458:9:0;120444:10;:23;120436:32;;;;;;152374:12;;152481:26;;152350:21;;;;152520:44;;:::i;:::-;152622:7;:14;152608:44;;;152622:29;;;152608:44;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;152608:44:0;-1:-1:-1;152575:30:0;;;;:77;;;;152688:7;152663:32;;;;;;;;;;;;;;;;;;;;;152688:7;152663:32;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;152663:32:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;152663:22:0;;;:32;152735:1;152706:26;;;:30;152777:7;:14;152747:27;;;:44;152804:43;;:::i;:::-;152907:7;:14;152893:44;;;152907:29;;;152893:44;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;152893:44:0;-1:-1:-1;152858:32:0;;;:79;152955:9;152950:1809;152970:15;;;152950:1809;;;153007:14;153024:38;153044:8;153054:4;;153059:1;153054:7;;;;;;;;;;;;153024:38;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;153024:19:0;;-1:-1:-1;;153024:38:0:i;:::-;153007:55;;153093:7;-1:-1:-1;;;;;153083:17:0;:6;-1:-1:-1;;;;;153083:17:0;;153079:134;;;153189:8;;;153079:134;153242:7;-1:-1:-1;;;;;153233:16:0;:6;-1:-1:-1;;;;;153233:16:0;;153229:182;;;153390:5;;;153229:182;-1:-1:-1;;;;;153449:25:0;;153427:19;153449:25;;;:17;:25;;;;;;;;;153506:23;;;:10;:23;;;;;;:30;;153567;;;;153643:41;;;;;153612:72;;;153506:30;;-1:-1:-1;;;153567:30:0;;;;;153705:73;;153567:30;;153506;;153764:13;153705:12;:73::i;:::-;153701:1047;;;153876:23;;;;:10;:23;;;;;:39;;;153809:6;;-1:-1:-1;153809:6:0;;153855:73;;153921:6;;153855:61;;:16;;:61;:20;:61;:::i;:::-;:65;:73;:65;:73;:::i;:::-;153953:28;;153836:92;;-1:-1:-1;153953:33:0;153949:386;;154147:11;154085:10;:32;;;154118:10;:25;;;154085:59;;;;;;;;;;;;;;;;;:73;154181:25;;;:27;;;;;;153949:386;;;154271:44;154295:11;154308:6;154271:23;:44::i;:::-;154257:58;;153949:386;153701:1047;;;154370:13;154360:6;:23;;;;;;;;;154356:392;;;154619:11;154550;:30;;;154581:11;:34;;;154550:66;;;;;;;;;;;;;;;;;;:80;;;;154649:36;;;;;;;;154704:26;;;:28;;;;;;;154356:392;152950:1809;;;;;152987:3;;152950:1809;;;;154843:48;154867:11;154888:1;154843:23;:48::i;:::-;154829:62;;154924:367;154976:13;155008:8;155035:16;155070:9;155098:11;:30;;;155147:11;:34;;;155200:10;:32;;;155251:10;:25;;;154924:33;:367::i;:::-;154904:387;152115:3184;-1:-1:-1;;;;;;;;;;;;;152115:3184:0:o;122231:29::-;;;-1:-1:-1;;;;;122231:29:0;;:::o;123000:28::-;;;;:::o;123250:47::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;123250:47:0;;;;;;;;-1:-1:-1;;;123250:47:0;;;;;;;:::o;123304:52::-;;;;;;;;;;;;;:::o;136173:283::-;136241:7;136264:25;136293:50;136331:11;136293:37;:50::i;:::-;136361:23;;;;:10;:23;;;;;:40;;;136261:82;;-1:-1:-1;136361:87:0;;-1:-1:-1;122133:1:0;;136361:63;;136261:82;136361:63;:44;:63;:::i;:87::-;136354:94;136173:283;-1:-1:-1;;;136173:283:0:o;122566:25::-;;;;:::o;124345:37::-;;;;:::o;141554:389::-;25383:19;:17;:19::i;:::-;141747:20;141770:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;141770:39:0;141828:28;141820:37;;;;;;141868:67;;;-1:-1:-1;;;141868:67:0;;-1:-1:-1;;;;;141868:67:0;;;;;;;;;;;;;;;;;;;;;;:35;;;;;;:67;;;;;-1:-1:-1;;141868:67:0;;;;;;;;-1:-1:-1;141868:35:0;:67;;;5:2:-1;;;;30:1;27;20:12;143409:262:0;143470:7;-1:-1:-1;;;;;143494:20:0;;;;:56;;-1:-1:-1;143518:11:0;;:27;;;-1:-1:-1;;;143518:27:0;;-1:-1:-1;;;;;143518:27:0;;;;;;;;;:11;;;;;:21;;:27;;;;;;;;;;;;;;:11;:27;;;5:2:-1;;;;30:1;27;20:12;5:2;143518:27:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;143518:27:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;143518:27:0;:32;143494:56;143490:97;;;-1:-1:-1;143574:1:0;143567:8;;143490:97;143615:11;;:40;;;-1:-1:-1;;;143615:40:0;;-1:-1:-1;;;;;143615:40:0;;;;;;;143604:52;143615:40;;;;;;;;143604:10;;143615:11;;;;;:31;;:40;;;;;;;;;;;;;;:11;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;143615:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;143615:40:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;143615:40:0;143604:52;;143615:40;143604:52;;;;;;;;-1:-1:-1;143604:52:0;:59;;143409:262;-1:-1:-1;;143409:262:0:o;122715:32::-;;;;:::o;122756:33::-;;;;:::o;146486:481::-;25785:17;:15;:17::i;:::-;146728:18;;146700:25;:23;:25::i;:::-;:46;146692:72;;;;;-1:-1:-1;;;146692:72:0;;;;;;;;;;;;-1:-1:-1;;;146692:72:0;;;;;;;;;;;;;;;146793:10;;146783:6;:20;;146775:51;;;;;-1:-1:-1;;;146775:51:0;;;;;;;;;;;;-1:-1:-1;;;146775:51:0;;;;;;;;;;;;;;;146837:56;146855:4;146861:10;146873:11;146886:6;146837:17;:56::i;:::-;146904:55;146914:4;146920:6;146928:16;146946:12;146904:9;:55::i;:::-;;146486:481;;;;;:::o;144640:627::-;144893:10;144915:4;144893:27;144885:51;;;;;-1:-1:-1;;;144885:51:0;;;;;;;;;;;;-1:-1:-1;;;144885:51:0;;;;;;;;;;;;;;;144968:59;144986:11;144999;145012;145025:1;144968:17;:59::i;:::-;145038:35;145047:11;145060:12;;145038:8;:35::i;:::-;145086:22;145111:69;145121:11;145134:13;145149:16;145167:12;;145111:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;145111:9:0;;-1:-1:-1;;;145111:69:0:i;:::-;145191:6;;:68;;;-1:-1:-1;;;145191:68:0;;;;;;;;;;;;;;;;;;;;;;145086:94;;-1:-1:-1;;;;;;145191:6:0;;;;:24;;:68;;;;;:6;;:68;;;;;;;;:6;;:68;;;5:2:-1;;;;30:1;27;20:12;5:2;145191:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;145191:68:0;;;;144640:627;;;;;;;;:::o;123611:51::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;123611:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;123611:51:0;;;-1:-1:-1;;;123611:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;123212:29::-;;;;;;:::o;122835:25::-;;;;:::o;137098:146::-;137170:7;137197:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;137197:39:0;;137098:146::o;25204:29::-;;;;;;-1:-1:-1;;;;;25204:29:0;;:::o;135262:87::-;135333:8;;-1:-1:-1;;;;;135333:8:0;135262:87;;:::o;156101:1823::-;156205:8;;;156196:46;;;-1:-1:-1;;;156196:46:0;;;;156168:7;;156246:10;;-1:-1:-1;;;;;156205:8:0;;156196:44;;:46;;;;;;;;;;;156205:8;156196:46;;;5:2:-1;;;;30:1;27;20:12;5:2;156196:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;156196:46:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;156196:46:0;-1:-1:-1;;;;;156196:60:0;;156188:90;;;;;-1:-1:-1;;;156188:90:0;;;;;;;;;;;;-1:-1:-1;;;156188:90:0;;;;;;;;;;;;;;;156291:43;156337:38;:29;:17;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;156337:27:0;;-1:-1:-1;;;156337:29:0:i;:::-;:36;:38::i;:::-;156291:84;;156386:16;156413:20;156444:19;156474:9;156496:1281;156507:16;:23;156503:1;:27;156496:1281;;;156552:36;156591:28;:16;156608:1;156591:19;;;;;;;;;;;;;;:26;:28::i;:::-;156552:67;;156636:19;156658:21;:9;156668:1;156658:12;;;;;;;;;;;;;;:19;:21::i;:::-;156636:43;;156694:27;156709:11;156694:14;:27::i;:::-;156738:15;156756:21;:9;156766:1;156756:12;;;;;;;:21;156738:39;-1:-1:-1;156806:24:0;:11;156738:39;156806:24;:15;:24;:::i;:::-;156847:26;156876:23;;;:10;:23;;;;;:39;;;156792:38;;-1:-1:-1;;;;;;156876:39:0;156934:34;;156930:402;;156989:24;157105:23;;;:10;:23;;;;;;;;:30;;157162:39;;;;;157037:221;;-1:-1:-1;;;157037:221:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;157037:41:0;;;;;:221;;;;;;;;;;;156989:24;157037:41;:221;;;5:2:-1;;;;30:1;27;20:12;5:2;157037:221:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;157037:221:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;157037:221:0;;-1:-1:-1;157287:29:0;:7;157037:221;157287:29;:11;:29;:::i;:::-;157277:39;;156930:402;;157348:29;157380:23;;;:10;:23;;;;;:30;:43;;157415:7;157380:43;:34;:43;:::i;:::-;157438:23;;;;:10;:23;;;;;:54;;;157348:75;-1:-1:-1;157513:26:0;157509:257;;157560:35;157569:11;157582:12;;157560:8;:35::i;:::-;157509:257;;;157621:24;:9;157631:1;157621:12;;;;;;;;;;;;;;:22;:24::i;:::-;157617:149;;;157681:39;157698:21;157704:11;157717:1;157698:5;:21::i;:::-;157681:12;;:39;:16;:39;:::i;:::-;157739:11;;;;;157666:54;-1:-1:-1;157617:149:0;-1:-1:-1;;156532:3:0;;;;;-1:-1:-1;156496:1281:0;;-1:-1:-1;;156496:1281:0;;157816:69;157839:29;:11;157855:12;157839:29;:15;:29;:::i;:::-;157831:38;;157872:9;157871:10;;157883:1;157816:14;:69::i;:::-;-1:-1:-1;157905:11:0;156101:1823;-1:-1:-1;;;;;;156101:1823:0:o;138956:542::-;25383:19;:17;:19::i;:::-;139191:13;;139219:260;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;139219:260:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;139164:326:0;;-1:-1:-1;;;;;139191:13:0;;139164:12;:326::i;:::-;138956:542;;;:::o;135417:118::-;135499:11;;:28;;;-1:-1:-1;;;135499:28:0;;;;;;;;;;135472:7;;-1:-1:-1;;;;;135499:11:0;;:19;;:28;;;;;;;;;;;;;;:11;:28;;;5:2:-1;;;;30:1;27;20:12;142638:150:0;25785:17;:15;:17::i;:::-;142729:51;142747:4;142753:10;142765:11;142778:1;142729:17;:51::i;142796:605::-;143095:16;;143032:38;;;143043:10;143032:38;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;143032:38:0;;;;;;;143022:49;;;;;:97;;143088:5;;143113;143022:97;:65;:97;:::i;:::-;143000:162;;;;;-1:-1:-1;;;143000:162:0;;;;;;;;;;;;-1:-1:-1;;;143000:162:0;;;;;;;;;;;;;;;143229:10;143173:22;143217:23;;;:11;:23;;;;;;143198:43;;:14;;:43;:18;:43;:::i;:::-;143173:68;;143252:37;143262:10;143274:14;143252:9;:37::i;:::-;143312:10;143300:23;;;;:11;:23;;;;;:40;;;143351:42;;143378:14;143351;:42::i;146231:247::-;146394:4;146372:11;133236:30;133254:11;133236:17;:30::i;:::-;146418:5;;:52;;;-1:-1:-1;;;146418:52:0;;-1:-1:-1;;;;;146418:52:0;;;;;;;146456:4;146418:52;;;;;;;;;;;;:5;;;;;:18;;:52;;;;;;;;;;;;;;:5;;:52;;;5:2:-1;;;;30:1;27;20:12;5:2;146418:52:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;146418:52:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;146418:52:0;;146231:247;-1:-1:-1;;;;;146231:247:0:o;122450:22::-;;;;:::o;47147:140::-;46569:9;:7;:9::i;:::-;46561:18;;;;;;47230:6;;47209:40;;47246:1;;-1:-1:-1;;;;;47230:6:0;;47209:40;;47246:1;;47209:40;47260:6;:19;;-1:-1:-1;;;;;;47260:19:0;;;47147:140::o;122377:27::-;;;;:::o;123171:34::-;;;;:::o;123518:46::-;;;;;;;;;;;;;:::o;122169:23::-;;;-1:-1:-1;;;;;122169:23:0;;:::o;124466:36::-;;;;:::o;122502:32::-;;;;:::o;155739:354::-;155838:7;155816:11;133236:30;133254:11;133236:17;:30::i;:::-;155858:27;155873:11;155858:14;:27::i;:::-;155898:19;155920:23;;;:10;:23;;;;;:40;;;:64;;122133:1;155920:64;:44;:64;:::i;:::-;155995:23;;;;:10;:23;;;;;122133:1;155995:40;;;;:61;155898:86;-1:-1:-1;;155739:354:0;;;;:::o;136024:141::-;136091:7;136118:23;;;:10;:23;;;;;:39;;;;136024:141::o;136847:117::-;136930:26;;136847:117;:::o;122802:26::-;;;;:::o;150862:226::-;150963:11;133236:30;133254:11;133236:17;:30::i;:::-;151029:23;;;;:10;:23;;;;;:39;;;:51;;151073:6;151029:51;:43;:51;:::i;:::-;150987:23;;;;:10;:23;;;;;;:39;;:93;;;;-1:-1:-1;;150862:226:0:o;123971:24::-;;;;;;-1:-1:-1;;;;;123971:24:0;;:::o;46357:79::-;46422:6;;-1:-1:-1;;;;;46422:6:0;46357:79;:::o;134950:255::-;135051:38;;;;;;;;;;;;;;;;135134:15;135177:10;-1:-1:-1;;;;;135177:20:0;;;;134950:255;:::o;135543:85::-;135608:12;;135543:85;:::o;137802:121::-;25383:19;:17;:19::i;:::-;137880:35;137889:11;137902:12;;137880:8;:35::i;:::-;137802:121;:::o;124156:32::-;;;;:::o;149133:176::-;149197:11;132987:26;133001:11;132987:13;:26::i;:::-;149221:27;149236:11;149221:14;:27::i;:::-;149259:42;149277:11;149290:10;149259:17;:42::i;120196:24::-;;;-1:-1:-1;;;;;120196:24:0;;:::o;144191:441::-;25785:17;:15;:17::i;:::-;144374:13;;144402:211;;;;;;;;;;;;;;;144593:4;144402:211;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;144402:211:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;144347:277:0;;-1:-1:-1;;;;;144374:13:0;;144347:12;:277::i;123784:31::-;;;;:::o;140964:270::-;25383:19;:17;:19::i;:::-;141052:6;;141100:13;;141052:62;;;-1:-1:-1;;;141052:62:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;141052:6:0;;;;:29;;:62;;;;;:6;;:62;;;;;;;;:6;;:62;;;5:2:-1;;;;30:1;27;20:12;5:2;141052:62:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;141052:62:0;;;;121959:3;141133:16;:38;;141125:58;;;;;-1:-1:-1;;;141125:58:0;;;;;;;;;;;;-1:-1:-1;;;141125:58:0;;;;;;;;;;;;;;;141194:13;:32;140964:270::o;139543:370::-;46569:9;:7;:9::i;:::-;46561:18;;;;;;139677:13;;139705:189;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;139705:189:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;139650:255:0;;-1:-1:-1;;;;;139677:13:0;;139650:12;:255::i;149777:870::-;149865:11;133236:30;133254:11;133236:17;:30::i;:::-;149902:1;149893:6;:10;149889:142;;;149975:17;;;;149967:52;;;;;-1:-1:-1;;;149967:52:0;;;;;;;;;;;;-1:-1:-1;;;149967:52:0;;;;;;;;;;;;;;;150043:25;150071:23;;;:10;:23;;;;;:41;;;150129:22;150125:287;;150220:28;150235:6;150243:1;150246;150220:14;:28::i;:::-;150125:287;;;150290:12;;150270:17;:32;150266:146;;;150381:19;;;-1:-1:-1;;;150381:19:0;;;;;;;;;;;;-1:-1:-1;;;150381:19:0;;;;;;;;;;;;;;150266:146;150448:1;150438:6;:11;150434:206;;150466:62;150499:11;150520:6;150466:32;:62::i;:::-;150434:206;;;150561:67;150594:11;150615:6;-1:-1:-1;;150615:11:0;150561:32;:67::i;138560:162::-;25383:19;:17;:19::i;:::-;138657:12;138649:21;;;;;;138681:23;:33;138560:162::o;136972:118::-;137061:14;:21;136972:118;:::o;143679:504::-;25785:17;:15;:17::i;:::-;143899:13;;143927:237;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;143872:303;;-1:-1:-1;;;;;143899:13:0;;-1:-1:-1;;;143968:58:0;144045:11;;144075:6;;144100:17;;144136:13;;;;143927:237;;144136:13;;;;143927:237;1:33:-1;99:1;81:16;;;74:27;143927:237:0;;;-1:-1:-1;;137:4;117:14;;;113:30;;157:16;;;26:21;;;22:32;;;6:49;;143927:237:0;-1:-1:-1;49:4;25:18;;61:17;;-1:-1;;;;;;143927:237:0;;;;-1:-1:-1;;;;;182:15;;;179:29;;;;160:49;;;-1:-1;143872:12:0;;-1:-1:-1;;;;;;143872:303:0:i;:::-;143679:504;;;;;:::o;26348:73::-;25383:19;:17;:19::i;:::-;26399:14;:12;:14::i;:::-;26348:73::o;135636:99::-;135711:16;;135636:99;:::o;124002:29::-;;;;:::o;141951:130::-;25383:19;:17;:19::i;:::-;142038:35;142053:11;142066:6;142038:14;:35::i;141366:180::-;25383:19;:17;:19::i;:::-;141471:10;:24;;;;141506:14;:32;141366:180::o;136464:375::-;136531:7;136590:23;;;:10;:23;;;;;:41;;;136531:7;;136586:152;;136676:50;136714:11;136676:37;:50::i;:::-;-1:-1:-1;136653:73:0;-1:-1:-1;136586:152:0;136755:23;;;;:10;:23;;;;;122133:1;136755:30;;;;:76;;122133:1;136755:52;;136790:16;136755:52;:34;:52;:::i;145821:402::-;145952:4;145991:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;145991:39:0;146034:10;145991:53;;:134;;-1:-1:-1;146074:8:0;;;146065:46;;;-1:-1:-1;;;146065:46:0;;;;146115:10;;-1:-1:-1;;;;;146074:8:0;;;;146065:44;;:46;;;;;;;;;;;;;146074:8;146065:46;;;5:2:-1;;;;30:1;27;20:12;5:2;146065:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;146065:46:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;146065:46:0;-1:-1:-1;;;;;146065:60:0;;145991:134;145969:195;;;;;-1:-1:-1;;;145969:195:0;;;;;;;;;;;;-1:-1:-1;;;145969:195:0;;;;;;;;;;;;;;;146182:5;;:33;;;-1:-1:-1;;;146182:33:0;;-1:-1:-1;;;;;146182:33:0;;;;;;;;;;;;;;;:5;;;;;:14;;:33;;;;;;;;;;;;;;:5;;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;146182:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;146182:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;146182:33:0;;145821:402;-1:-1:-1;;;;145821:402:0:o;140126:270::-;25383:19;:17;:19::i;:::-;140311:4;-1:-1:-1;;;;;140256:60:0;140272:18;-1:-1:-1;;;;;140256:41:0;;:43;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;140256:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;140256:43:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140256:43:0;-1:-1:-1;;;;;140256:60:0;;140248:69;;;;;;140328:23;;;;:10;:23;;;;;;:39;;:60;;-1:-1:-1;;;;;;140328:60:0;-1:-1:-1;;;;;140328:60:0;;;;;;;;;140126:270::o;138730:218::-;25383:19;:17;:19::i;:::-;138822:14;138814:23;;;;;;138848:6;;138882:17;;138848:52;;;-1:-1:-1;;;138848:52:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;138848:6:0;;;;:22;;:52;;;;;:6;;:52;;;;;;;;:6;;:52;;;5:2:-1;;;;30:1;27;20:12;5:2;138848:52:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;138911:17:0;:29;;;;-1:-1:-1;138730:218:0:o;122901:37::-;;;;:::o;25719:18::-;;;;;;:::o;159915:641::-;160027:10;159987:19;160009:29;;;:17;:29;;;;;;;;;160102:23;;;:10;:23;;;;;;:30;;;;160151;;160200:41;;;;;160260:12;;160071:216;;-1:-1:-1;;;160102:30:0;;;;;;160151;160200:41;160071:12;:216::i;:::-;160049:279;;;;;-1:-1:-1;;;160049:279:0;;;;;;;;;;;;-1:-1:-1;;;160049:279:0;;;;;;;;;;;;;;;160341:20;160364:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;160364:39:0;160422:28;160414:63;;;;;-1:-1:-1;;;160414:63:0;;;;;;;;;;;;-1:-1:-1;;;160414:63:0;;;;;;;;;;;;;;;160490:58;;;-1:-1:-1;;;160490:58:0;;;;;;;;;;;-1:-1:-1;;;;;160490:46:0;;;;;:58;;;;;-1:-1:-1;;160490:58:0;;;;;;;-1:-1:-1;160490:46:0;:58;;;5:2:-1;;;;30:1;27;20:12;5:2;160490:58:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;160490:58:0;;;;159915:641;;;:::o;123717:58::-;;;;;;;;;;;;;:::o;146975:1179::-;147036:11;132987:26;133001:11;132987:13;:26::i;:::-;147060:25;147088:23;;;:10;:23;;;;;:41;;;147223:21;;;;;:97;;-1:-1:-1;147308:12:0;;147287:16;;147265:39;;:17;;:39;:21;:39;:::i;:::-;:55;;147223:97;:167;;;;-1:-1:-1;147375:15:0;147341:23;;;;:10;:23;;;;;:30;;;-1:-1:-1;;;147341:30:0;;;;:49;;;;;;;;;;147223:167;147201:200;;;;;;147414:14;147431:23;;;:10;:23;;;;;:30;147497:11;;147431:30;;147414:14;147497:23;;147431:30;147497:23;:15;:23;:::i;:::-;147531:11;:28;;;147472:48;-1:-1:-1;147643:42:0;147661:11;147674:10;147643:17;:42::i;:::-;147698:11;;:29;;;-1:-1:-1;;;147698:29:0;;;;;;;;;;-1:-1:-1;;;;;147698:11:0;;;;:16;;:29;;;;;:11;;:29;;;;;;;;:11;;:29;;;5:2:-1;;;;30:1;27;20:12;5:2;147698:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;147773:1:0;147740:23;;;:10;:23;;;;;:34;;;147785:32;;;:36;;;;147832:30;;;:43;;-1:-1:-1;;;;;;147832:43:0;;;-1:-1:-1;;147888:49:0;:74;147973:30;;:48;;-1:-1:-1;;;;147973:48:0;-1:-1:-1;;;147973:48:0;;;-1:-1:-1;148034:34:0;148049:10;148061:6;148034:14;:34::i;:::-;148079:6;;:67;;;-1:-1:-1;;;148079:67:0;;148098:10;148079:67;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;148079:6:0;;;;:18;;:67;;;;;:6;;:67;;;;;;;;:6;;:67;;;5:2:-1;;;;30:1;27;20:12;155307:424:0;155405:11;132987:26;133001:11;132987:13;:26::i;:::-;155429:27;155444:11;155429:14;:27::i;:::-;155496:13;;155524:188;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;155524:188:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;155469:254:0;;-1:-1:-1;;;;;155496:13:0;;155469:12;:254::i;124257:42::-;;;;:::o;123415:27::-;;;;;;:::o;140404:351::-;25383:19;:17;:19::i;:::-;140506:1;140493:10;:14;140485:23;;;;;;140519:6;;140560:7;;140519:49;;;-1:-1:-1;;;140519:49:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;140519:6:0;;;;:28;;:49;;;;;:6;;:49;;;;;;;;:6;;:49;;;5:2:-1;;;;30:1;27;20:12;5:2;140519:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;140579:7:0;:20;;;-1:-1:-1;140610:16:0;:29;;;140666:17;140589:10;140681:1;140666:17;:14;:17;:::i;:::-;140650:13;:33;;;140716:12;;:31;;;:16;:31;:::i;:::-;140694:19;:53;-1:-1:-1;140404:351:0:o;120634:210::-;46569:9;:7;:9::i;:::-;46561:18;;;;;;-1:-1:-1;;;;;120717:26:0;;120709:35;;;;;;120777:9;;120760:41;;-1:-1:-1;;;;;120760:41:0;;;;120777:9;;120760:41;;120777:9;;120760:41;120812:9;:24;;-1:-1:-1;;;;;;120812:24:0;-1:-1:-1;;;;;120812:24:0;;;;;;;;;;120634:210::o;135743:131::-;135809:7;135836:23;;;:10;:23;;;;;:30;;135743:131::o;122199:25::-;;;-1:-1:-1;;;;;122199:25:0;;:::o;137632:112::-;25383:19;:17;:19::i;:::-;137709:17;:27;;-1:-1:-1;;137709:27:0;;;;;;;;;;137632:112::o;47464:109::-;46569:9;:7;:9::i;:::-;46561:18;;;;;;47537:28;47556:8;47537:18;:28::i;151096:1011::-;151184:11;132987:26;133001:11;132987:13;:26::i;:::-;151208:14;151225:33;151245:12;151225:19;:33::i;:::-;151293:12;;151382:17;;151269:21;151341:36;;;:23;:36;;;;;;151208:50;;-1:-1:-1;151293:12:0;;151341:59;;;:40;:59;:::i;:::-;151324:13;:76;;151316:100;;;;;-1:-1:-1;;;151316:100:0;;;;;;;;;;;;-1:-1:-1;;;151316:100:0;;;;;;;;;;;;;;;151429:21;151453:23;;;:10;:23;;;;;;;;:30;;;;;151526:6;;:72;;-1:-1:-1;;;151526:72:0;;;;;;;;-1:-1:-1;;;;;151453:30:0;;;151526:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;151453:30;;151526:6;;;;;:22;;151453:23;;:30;;151526:72;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;151526:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;151526:72:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;151623:23:0;;;;:10;:23;;;;;:41;;;:46;151619:200;;-1:-1:-1;151619:200:0;;151743:28;151757:13;151743;:28::i;:::-;151786:21;151800:6;151786:13;:21::i;:::-;-1:-1:-1;;;;;151831:32:0;;;;;;;:17;:32;;;;;;;;-1:-1:-1;;151831:57:0;;151899:25;;;;;;;;;;:39;;;151949:23;;;:10;:23;;;;;:30;;:39;;-1:-1:-1;;;;;;151949:39:0;;;;;;;152047:23;:36;;;;:52;;;;-1:-1:-1;;151096:1011:0:o;133548:1394::-;63699:6;;;;63698:7;63690:34;;;;;-1:-1:-1;;;63690:34:0;;;;;;;;;;;;-1:-1:-1;;;63690:34:0;;;;;;;;;;;;;;;63735:6;:13;;-1:-1:-1;;63735:13:0;63744:4;63735:13;;;133890:26;133901:14;133890:10;:26::i;:::-;133882:61;;;;;-1:-1:-1;;;133882:61:0;;;;;;;;;;;;-1:-1:-1;;;133882:61:0;;;;;;;;;;;;;;;133954:13;:30;;-1:-1:-1;;;;;;133954:30:0;;;-1:-1:-1;;;;;133954:30:0;;;;;;;;;;-1:-1:-1;133995:37:0;;-1:-1:-1;;;;;;133995:37:0;133954:30;133995:37;;;;;;;134043:8;:20;;;;;;;;;;134074:9;:22;;;;;;;;;;134107:5;:22;;;;;;;;;;134140:11;:38;;;;;;;;;;134189:6;:36;;;;;;;;;;134236:21;:69;;;;;;;;;;;;;;134316:26;134335:6;134316:18;:26::i;:::-;-1:-1:-1;;134375:5:0;134355:16;:26;-1:-1:-1;;134422:1:0;134407:12;:16;;;134444:3;134434:7;:13;;;134501:16;134481:17;:36;134567:6;134553:10;:21;;;134603:14;:25;134683:4;134657:23;:30;134718:3;134698:17;:23;134755:1;134734:18;:22;134773:10;:14;;;134814:11;134798:13;:27;134856:13;:18;134910:17;:24;;-1:-1:-1;;134910:24:0;;;;;;-1:-1:-1;;;;;133548:1394:0:o;140813:143::-;25383:19;:17;:19::i;:::-;140915:12;;:33;;140932:15;140915:33;:16;:33;:::i;26271:69::-;25383:19;:17;:19::i;:::-;26320:12;:10;:12::i;124038:28::-;;;-1:-1:-1;;;;;124038:28:0;;:::o;149317:452::-;149537:1;149521:13;:17;149513:47;;;;;-1:-1:-1;;;149513:47:0;;;;;;;;;;;;-1:-1:-1;;;149513:47:0;;;;;;;;;;;;;;;149587:27;;;;:10;:27;;;;;;:43;;;149571:91;;-1:-1:-1;;;149571:91:0;;149643:10;149571:91;;;;;;;;;;;;-1:-1:-1;;;;;149587:43:0;;;;149571:71;;:91;;;;;;;;;;;149587:27;:43;149571:91;;;5:2:-1;;;;30:1;27;20:12;5:2;149571:91:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;149689:25:0;;;;:10;:25;;;;;;:41;;;149673:88;;-1:-1:-1;;;149673:88:0;;149742:10;149673:88;;;;;;;;;;;;-1:-1:-1;;;;;149689:41:0;;;;-1:-1:-1;149673:68:0;;:88;;;;;149689:25;;149673:88;;;;;;149689:25;:41;149673:88;;;5:2:-1;;;;30:1;27;20:12;122616:29:0;;;;:::o;122143:19::-;;;-1:-1:-1;;;;;122143:19:0;;:::o;25430:182::-;25527:10;;;;;-1:-1:-1;;;;;25527:10:0;25505;:33;25483:121;;;;-1:-1:-1;;;25483:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27459:274;27519:4;-1:-1:-1;;;;;27540:21:0;;27536:66;;-1:-1:-1;27585:5:0;27578:12;;27536:66;-1:-1:-1;27669:20:0;27717:8;;;27459:274::o;133041:131::-;133117:11;;:32;;;-1:-1:-1;;;133117:32:0;;;;;;;;;;133153:10;;-1:-1:-1;;;;;133117:11:0;;:19;;:32;;;;;;;;;;;;;;:11;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;133117:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;133117:32:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;133117:32:0;-1:-1:-1;;;;;133117:46:0;;133109:55;;;;;3325:150;3383:7;3415:5;;;3439:6;;;;3431:15;;;;;158957:950;159095:16;159091:809;;159196:1;159187:6;:10;159183:245;;;159242:14;:21;:42;;159276:6;159242:42;:25;:42;:::i;:::-;159218:14;:66;159183:245;;;159319:1;159310:6;:10;159306:122;;;159365:14;:21;:47;;159399:11;;;;159365:47;:25;:47;:::i;:::-;159341:14;:71;159306:122;159462:1;159448:11;:15;159444:285;;;159513:26;;:52;;159552:11;159513:52;:30;:52;:::i;:::-;159484:26;:81;159444:285;;;159605:1;159591:11;:15;159587:142;;;159656:26;;:57;;159695:16;;;;159656:57;:30;:57;:::i;:::-;159627:26;:86;159587:142;159091:809;;;159761:34;;;;:21;:34;;;;;:51;;;;;;-1:-1:-1;159827:46:0;:61;;;;;;158957:950;;;:::o;160935:304::-;161103:4;161137:1;161128:6;:10;:75;;;;-1:-1:-1;161143:22:0;;;:59;;;161189:13;161169:17;:33;161143:59;161128:102;;;;-1:-1:-1;161217:13:0;161207:6;:23;;;;;;;;;161128:102;161120:111;160935:304;-1:-1:-1;;;;;160935:304:0:o;25830:85::-;25890:6;;;;25889:7;25881:26;;;;;-1:-1:-1;;;25881:26:0;;;;;;;;;;;;-1:-1:-1;;;25881:26:0;;;;;;;;;;;;;;175948:218;176088:5;;:45;;;-1:-1:-1;;;176088:45:0;;-1:-1:-1;;;;;176088:45:0;;;;;;;;;;;;;;;;;;;;;;:5;;;;;:18;;:45;;;;;;;;;;;;;;:5;;:45;;;5:2:-1;;;;30:1;27;20:12;5:2;176088:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;176088:45:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;176088:45:0;176080:78;;;;;-1:-1:-1;;;176080:78:0;;;;;;;;;;;;-1:-1:-1;;;176080:78:0;;;;;;;;;;;;;;168337:140;168401:68;168425:11;168438:14;;168454;;168401:23;:68::i;3087:150::-;3145:7;3178:1;3173;:6;;3165:15;;;;;;-1:-1:-1;3203:5:0;;;3087:150::o;173787:1104::-;174008:27;174023:11;174008:14;:27::i;:::-;174048:14;174065:23;;;:10;:23;;;;;:30;;174126:20;174076:11;174126:7;:20::i;:::-;174159:23;;;;:10;:23;;;;;:41;;;:53;;;174302:39;;;;174384;;;;;174106:40;;-1:-1:-1;174302:39:0;-1:-1:-1;;;;;174384:39:0;174438:32;;174434:107;;174503:18;-1:-1:-1;;;;;174487:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;174487:42:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;174487:42:0;;;;174434:107;174567:23;;;;:10;:23;;;;;:30;;;174553:45;;-1:-1:-1;;;;;174567:30:0;174553:13;:45::i;:::-;174609:41;174627:11;174640:9;174609:17;:41::i;:::-;174663:19;174698:12;;174685:9;:25;;:41;;174717:9;174685:41;;;174713:1;174685:41;174663:63;;174737:69;174771:16;174761:6;174754:33;174752:36;;-1:-1:-1;;174794:11:0;174737:14;:69::i;:::-;174819:6;;:64;;;-1:-1:-1;;;174819:64:0;;-1:-1:-1;;;;;174819:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:6;;;;;:21;;:64;;;;;:6;;:64;;;;;;;:6;;:64;;;5:2:-1;;;;30:1;27;20:12;5:2;174819:64:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;174819:64:0;;;;173787:1104;;;;;;;:::o;21345:897::-;21563:10;;21607:2;21598:12;;21592:19;21654:2;21645:12;;21639:19;21449:7;;21563:10;21592:19;21630:29;;21699:66;21686:79;;21682:131;;;21797:3;21782:19;;;;;;;21682:131;21897:2;21893:1;:6;;;21889:46;;;21921:2;21916:7;21889:46;21951:1;:7;;21956:2;21951:7;;:18;;;;;21962:1;:7;;21967:2;21962:7;;21951:18;21947:70;;;22001:3;21986:19;;;;;;;21947:70;22096:24;;;22079:14;22096:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22079:14;;22096:24;;;;;;;-1:-1:-1;;22096:24:0;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;22096:24:0;;-1:-1:-1;;22096:24:0;;;-1:-1:-1;;;;;;;22185:22:0;;22177:31;;;;;;22228:6;21345:897;-1:-1:-1;;;;;;21345:897:0:o;161247:606::-;161386:32;;:::i;:::-;161468:7;:23;;;161443:7;:22;;;:48;:104;;;;;161541:6;-1:-1:-1;;;;;161495:52:0;:7;:18;;;161514:7;:22;;;161495:42;;;;;;;;;;;;;;-1:-1:-1;;;;;161495:52:0;;;161443:104;161436:348;;;161625:17;:61;161643:7;:18;;;161662:7;:22;;;161643:42;;;;;;;;;;;;;;-1:-1:-1;;;;;161625:61:0;-1:-1:-1;;;;;161625:61:0;;;;;;;;;;;;;161564:7;:26;;;161591:7;:30;;;161564:58;;;;;;;;;;;;;;;;;;:122;;;;161701:32;;;;;;;;161748:22;;;:24;;;;;;;161436:348;;;-1:-1:-1;;161796:22:0;;;:24;;;;;;:22;161247:606::o;164432:1818::-;164851:14;:21;164803:7;;164911:38;164947:1;164911:31;164940:1;164911:24;164851:21;164933:1;164911:24;:21;:24;:::i;:::-;:28;:31;:28;:31;:::i;:38::-;164891:16;:58;;164883:90;;;;;-1:-1:-1;;;164883:90:0;;;;;;;;;;;;-1:-1:-1;;;164883:90:0;;;;;;;;;;;;;;;164986:14;165003:78;165030:13;165045:16;165063:17;165003:26;:78::i;:::-;164986:95;;165094:22;165119:49;121959:3;165119:25;165130:13;;165119:6;:10;;:25;;;;:::i;:49::-;-1:-1:-1;;;;;165200:27:0;;165179:18;165200:27;;;:17;:27;;;;;;;;;165270:22;;;:10;:22;;;;;;165322:16;;;;165094:74;;-1:-1:-1;165200:27:0;;165322:36;;165094:74;165322:36;:20;:36;:::i;:::-;165303:16;;;:55;165450:16;:28;;;165491:25;165532:90;165551:70;165604:16;165551:48;122005:6;165551:26;:6;165562:14;165551:26;:10;:26;:::i;:::-;:30;:48;:30;:48;:::i;:70::-;165532:14;;;:90;:18;:90;:::i;:::-;165491:131;;165778:88;165803:18;165823:23;165848:17;165778:24;:88::i;:::-;165936:14;:34;;;166094:94;166119:21;166142:26;165953:17;166094:24;:94::i;:::-;166201:17;:15;:17::i;:::-;-1:-1:-1;166236:6:0;;164432:1818;-1:-1:-1;;;;;;;;;;;;;164432:1818:0:o;170731:704::-;170848:23;170941;;;:10;:23;;;;;:30;;171031:39;;;;;170848:23;;170941:30;170848:23;;171011:60;;170941:30;;171011:60;:19;:60;:::i;:::-;171082:22;171124:23;;;:10;:23;;;;;:45;;;171107:14;;170982:89;;-1:-1:-1;171107:62:0;;171200:227;171135:11;171281:15;171315:60;122005:6;171315:38;171107:62;170982:89;171315:38;:18;:38;:::i;:60::-;171394:18;171200:32;:227::i;:::-;171180:247;;;;;;;170731:704;;;:::o;176174:383::-;176345:14;;176338:3;:21;;176330:47;;;;;-1:-1:-1;;;176330:47:0;;;;;;;;;;;;-1:-1:-1;;;176330:47:0;;;;;;;;;;;;;;;176388:66;176407:4;176421;176428:25;:3;176436:16;176428:25;:7;:25;:::i;:::-;176388:18;:66::i;:::-;176484:16;;:25;;176505:3;176484:25;:20;:25;:::i;:::-;176465:16;:44;176520:6;;:29;;;-1:-1:-1;;;176520:29:0;;-1:-1:-1;;;;;176520:29:0;;;;;;;;;;;;;;;:6;;;;;:18;;:29;;;;;:6;;:29;;;;;;;:6;;:29;;;5:2:-1;;;;30:1;27;20:12;5:2;176520:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;176520:29:0;;;;176174:383;;;;:::o;172111:1668::-;172271:7;172291:14;172308:33;172328:12;172308:19;:33::i;:::-;172376:12;;172421:10;;172464:6;;172508:11;;172291:50;;-1:-1:-1;172376:12:0;;172421:10;;-1:-1:-1;;;;;172464:6:0;;172352:21;;172508:23;;172524:6;172508:23;:15;:23;:::i;:::-;172483:48;;172556:14;172542:11;:28;;;;172609:638;;;;;;;;172683:6;172609:638;;;;122133:1;172609:638;;;;172721:13;172609:638;;;;172768:1;172609:638;;;;172794:1;172609:638;;;;172818:6;-1:-1:-1;;;;;172609:638:0;;;;;172856:16;:137;;172989:3;172856:137;;;172892:21;;172952:8;;;172892:69;;;-1:-1:-1;;;172892:69:0;;;;;;;;-1:-1:-1;;;;;172892:69:0;;;;;;;172952:8;;;172892:69;;;;;:21;;;:28;;:69;;;;;;;;;;;;;;;:21;;:69;;;5:2:-1;;;;30:1;27;20:12;5:2;172892:69:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;172892:69:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;172892:69:0;172856:137;-1:-1:-1;;;;;172609:638:0;;;;;173016:13;172609:638;;173060:1;172609:638;;;;;;;;;;;;;;122133:1;172609:638;;;;;;;;;;;;;;173221:14;;172609:638;;;;;172583:23;;;:10;:23;;;;;;:664;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;172583:664:0;;;-1:-1:-1;;;;;;172583:664:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;172583:664:0;;;;-1:-1:-1;;;172583:664:0;;;;;;;;;;;;;;-1:-1:-1;172583:664:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;173260:36:0;;;:23;:36;;;;;;:52;;;173323:11;;:35;;-1:-1:-1;;;173323:35:0;;-1:-1:-1;;;;;173323:35:0;;;;;;;;;;;;;;;:11;;;;;:16;;:35;;;;;;;;;;-1:-1:-1;173323:11:0;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;173323:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;;;;;;173371:25:0;;;;;;:17;:25;;;;;:39;;;173421:36;;-1:-1:-1;173443:6:0;;173452:1;;173421:14;:36::i;:::-;173549:13;173506:16;:29;173523:11;173506:29;;;;;;;;;;;:40;;:56;;;;173573:7;-1:-1:-1;;;;;173573:17:0;;173591:6;173599:12;173613:11;173626:13;173641:6;173649:14;173573:91;;;;;;;;;;;;;-1:-1:-1;;;;;173573:91:0;-1:-1:-1;;;;;173573:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;173573:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;173573:91:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;173573:91:0;;;;173688:18;173704:1;173688:11;:15;;:18;;;;:::i;:::-;173675:10;:31;173719:21;173733:6;173719:13;:21::i;:::-;-1:-1:-1;173760:11:0;;172111:1668;-1:-1:-1;;;;;;;;172111:1668:0:o;5313:225::-;5374:14;;:::i;:::-;-1:-1:-1;5502:28:0;;;;;;;;;5510:11;;5502:28;;5467:4;5457:15;;;5502:28;;;;5313:225;;;:::o;6348:523::-;6408:16;6445:12;6452:4;6445:6;:12::i;:::-;6437:21;;;;;;6471:10;6484:14;6493:4;6484:8;:14::i;:::-;6471:27;;6509:23;6549:5;6535:20;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;6509:46;;6568:11;6596:27;6611:4;:11;;;6596:14;:27::i;:::-;6582:11;;;;:41;;-1:-1:-1;6634:12:0;;6657:181;6678:5;6674:1;:9;6657:181;;;6715:19;6727:6;6715:11;:19::i;:::-;6705:29;;6761:24;;;;;;;;6769:7;6761:24;;;;6778:6;6761:24;;;6749:6;6756:1;6749:9;;;;;;;;;;;;;;;;;:36;6810:16;;;;6685:3;;6657:181;;;-1:-1:-1;6857:6:0;;6348:523;-1:-1:-1;;;;;6348:523:0:o;8331:549::-;8416:8;;8391:4;;8416:12;;;;:30;;-1:-1:-1;8432:8:0;;8444:2;-1:-1:-1;8432:14:0;8416:30;8408:39;;;;;;8460:11;8474:27;8489:4;:11;;;8474:14;:27::i;:::-;8523:8;;8589:11;;;;;:20;;8654:13;;8460:41;;-1:-1:-1;8523:17:0;;;;;8654:13;8589:20;8745:11;;8742:2;;;8815:3;8811:2;8807:12;8802:3;8798:22;8790:6;8786:35;8776:45;;8742:2;-1:-1:-1;8866:6:0;8331:549;-1:-1:-1;;;;8331:549:0:o;7828:291::-;7916:8;;7891:4;;7928:1;7916:13;7908:22;;;;;;7977:11;;;;8041:13;;7941:11;8033:22;;8085:11;;:26;;8107:4;8085:26;;;8099:5;8085:26;8078:33;7828:291;-1:-1:-1;;;;7828:291:0:o;171443:660::-;171522:7;171571:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;171571:39:0;171625:34;;171621:109;;171692:18;-1:-1:-1;;;;;171676:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;171676:42:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;171676:42:0;;;;171621:109;171766:12;;171824:34;171766:12;171842:15;171824:34;:17;:34;:::i;:::-;171789:23;;;;:10;:23;;;;;;:32;;;;:69;;;;171869:30;;;:46;;-1:-1:-1;;;;171869:46:0;-1:-1:-1;;;171869:46:0;;;171926:6;;;171971:30;;;171926:76;;-1:-1:-1;;;171926:76:0;;;;;;;;;;;;;;-1:-1:-1;;;;;171971:30:0;;;171926:76;;;;;;:6;;;:16;;:76;;;;;171789:23;;171926:76;;;;;171789:23;171926:6;:76;;;5:2:-1;;;;30:1;27;20:12;5:2;171926:76:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;172055:23:0;;;;:10;:23;;;;;:39;;;;172020:30;;:75;;-1:-1:-1;172020:30:0;:75;:34;:75;:::i;26555:892::-;26920:1;26900;26871:9;26865:16;26841:4;26830:9;26826:20;26803:4;26778:5;26773:3;26769:15;26738:198;26962:14;27009:4;27003:11;27051:4;27048:1;27043:3;27028:28;27254:6;27278:66;;;;27405:4;27400:3;27393:17;27278:66;27320:4;27315:3;27308:17;23777:1128;23935:4;23975:2;23960:5;:12;:17;;;;;;:22;23952:55;;;;;-1:-1:-1;;;23952:55:0;;;;;;;;;;;;-1:-1:-1;;;23952:55:0;;;;;;;;;;;;;;;24018:19;24055:2;24040:5;:12;:17;;;;;;24018:39;;24217:11;24212:1;:16;24204:5;:24;24196:58;;;;;-1:-1:-1;;;24196:58:0;;;;;;;;;;;;-1:-1:-1;;;24196:58:0;;;;;;;;;;;;;;;24267:20;24321:4;24353:2;24336:520;24362:5;:12;24357:1;:17;24336:520;;24450:13;;;24444:20;;-1:-1:-1;24507:1:0;24499:5;:9;24495:316;;24598:12;24612;24581:44;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;24581:44:0;;;24549:95;;;;;;24534:110;;24495:316;;;24749:12;24763;24732:44;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;24732:44:0;;;24700:95;;;;;;24685:110;;24495:316;24843:1;24835:5;:9;;-1:-1:-1;24381:2:0;24376:7;24336:520;;;-1:-1:-1;24873:24:0;;;;23777:1128;-1:-1:-1;;;;;;23777:1128:0:o;176565:166::-;176652:16;;:28;;176673:6;176652:28;:20;:28;:::i;:::-;176633:16;:47;176691:6;;:32;;;-1:-1:-1;;;176691:32:0;;-1:-1:-1;;;;;176691:32:0;;;;;;;;;;;;;;;:6;;;;;:18;;:32;;;;;:6;;:32;;;;;;;:6;;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;176691:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;175789:151:0;175877:5;;:35;;;-1:-1:-1;;;175877:35:0;;-1:-1:-1;;;;;175877:35:0;;;;;;;;;;;;;;;:5;;;;;:14;;:35;;;;;;;;;;;;;;:5;;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;175877:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;175877:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;175877:35:0;175869:63;;;;;-1:-1:-1;;;175869:63:0;;;;;;;;;;;;-1:-1:-1;;;175869:63:0;;;;;;;;;;;;;;133294:170;133374:23;;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;133374:39:0;133417:10;133374:53;133366:90;;;;;-1:-1:-1;;;133366:90:0;;;;;;;;;;;;;;;;;;;;;;;;;;;175281:500;175371:14;175388:23;;;:10;:23;;;;;122133:1;175388:30;;;;:54;;;:34;:54;:::i;:::-;175478:22;;175371:71;;-1:-1:-1;175478:34:0;;175371:71;175478:34;:26;:34;:::i;:::-;175453:22;:59;175523:23;;;;:10;:23;;;;;122133:1;175523:30;;;:51;175633:14;;175585:45;;;;:62;175658:37;175673:13;175688:6;175658:14;:37::i;:::-;175706:6;;175750:22;;175706:67;;;-1:-1:-1;;;175706:67:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;175706:6:0;;;;:22;;:67;;;;;:6;;:67;;;;;;;;:6;;:67;;;5:2:-1;;;;30:1;27;20:12;150655:199:0;150795:23;;;;:10;:23;;;;;:39;;;:51;;150839:6;150795:51;:43;:51;:::i;:::-;150753:23;;;;:10;:23;;;;;;:39;;:93;;;;-1:-1:-1;150655:199:0:o;25986:58::-;26031:5;26022:14;;-1:-1:-1;;26022:14:0;;;25986:58::o;2646:303::-;2704:7;2803:1;2799;:5;2791:14;;;;;;2816:9;2832:1;2828;:5;;;;;;;2646:303;-1:-1:-1;;;;2646:303:0:o;47723:187::-;-1:-1:-1;;;;;47797:22:0;;47789:31;;;;;;47857:6;;47836:38;;-1:-1:-1;;;;;47836:38:0;;;;47857:6;;47836:38;;47857:6;;47836:38;47885:6;:17;;-1:-1:-1;;;;;;47885:17:0;-1:-1:-1;;;;;47885:17:0;;;;;;;;;;47723:187::o;160609:318::-;160678:7;160706:3;:10;160720:2;160706:16;160698:36;;;;;-1:-1:-1;;;160698:36:0;;;;;;;;;;;;-1:-1:-1;;;160698:36:0;;;;;;;;;;;;;;;160786:14;;;;;;-1:-1:-1;;;;;160822:20:0;;;;;;:54;;-1:-1:-1;;;;;;160846:25:0;;;;;;:17;:25;;;;;;:30;160822:54;160814:81;;;;;-1:-1:-1;;;160814:81:0;;;;;;;;;;;;-1:-1:-1;;;160814:81:0;;;;;;;;;;;;;;177197:569;177287:7;:14;;;177264:20;;-1:-1:-1;;177341:16:0;;177333:25;;;;;;;;;;;;;;;;;177376:7;:25;;-1:-1:-1;;;;;177333:25:0;;;;-1:-1:-1;177376:7:0;-1:-1:-1;;177384:16:0;;;177376:25;;;;;;;;;;;;;;;177369:32;;-1:-1:-1;;;;;;177369:32:0;;;-1:-1:-1;;177507:16:0;;177490:223;177525:5;;177490:223;;177570:14;-1:-1:-1;;;;;177556:28:0;:10;-1:-1:-1;;;;;177556:28:0;;177552:74;;;177605:5;;177552:74;177674:7;177686:1;177682;:5;177674:14;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;177674:14:0;177690:10;177655:7;177667:1;177663;:5;177655:14;;;;;;;;;;;;;;;;;177642:59;;-1:-1:-1;;;;;;177642:59:0;-1:-1:-1;;;;;177642:59:0;;;;;;;;;;;-1:-1:-1;;;177532:3:0;177490:223;;;-1:-1:-1;;;177742:16:0;;177725:33;:7;177742:16;177725:33;:::i;176739:450::-;176801:7;27:10:-1;;39:1;23:18;;45:23;;-1:-1;176801:23:0;;;;;;;-1:-1:-1;;;;;;176801:23:0;-1:-1:-1;;;;;176801:23:0;;;;;176854:14;-1:-1:-1;;176854:18:0;;176912:189;176919:5;;176912:189;;176946:14;176963:7;176975:1;176971;:5;176963:14;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;176963:14:0;;;;-1:-1:-1;176996:18:0;;;;176992:64;;;177035:5;;;176992:64;177083:6;177070:7;177078:1;177070:10;;;;;;;;;;;;;;;;;:19;;-1:-1:-1;;;;;;177070:19:0;-1:-1:-1;;;;;177070:19:0;;;;;;;;;;-1:-1:-1;;;176926:3:0;176912:189;;;177122:9;177117:1;:14;177113:69;;177161:9;177148:7;177156:1;177148:10;;;;;;;;;;;;;;;;:22;;;;;-1:-1:-1;;;;;177148:22:0;;;;;-1:-1:-1;;;;;177148:22:0;;;;;;176739:450;;;:::o;25923:55::-;25957:6;:13;;-1:-1:-1;;25957:13:0;25966:4;25957:13;;;25923:55::o;166683:1646::-;166848:29;166880:23;;;:10;:23;;;;;:45;;;167017;;;167013:1158;;;167079:23;167105;;;:10;:23;;;;;:30;;167176:39;;;;;167234:19;;167230:930;;167274:26;167303:36;:15;167323;167303:36;:19;:36;:::i;:::-;167274:65;;167358:419;167419:11;167453:15;167491;167529:229;167583:11;167621:18;167666:21;167714;167529:27;:229::i;:::-;167358:38;:419::i;:::-;167230:930;;;;167818:326;167865:11;167899:226;167953:11;167991:15;168033:21;168081;167899:27;:226::i;:::-;167818:24;:326::i;:::-;167013:1158;;;168207:21;168187:17;:41;168183:139;;;168245:23;;;;:10;:23;;;;;:45;;:65;;;166683:1646;;;;:::o;2078:433::-;2136:7;2380:6;2376:47;;-1:-1:-1;2410:1:0;2403:8;;2376:47;2447:5;;;2451:1;2447;:5;:1;2471:5;;;;;:10;2463:19;;;;;161861:2563;162525:23;;162579:17;;162025:7;;162525:23;162025:7;162631:69;162525:23;162640:13;162525:23;162640:35;;;;;162677:22;;162631:8;:69::i;:::-;162607:93;;162776:1;162760:13;:17;:55;;;;;162798:17;;162781:13;:34;;162760:55;162756:613;;;162836:17;;:22;162832:464;;162958:13;124146:3;162987:21;;162975:9;:33;:56;;;;;;162958:74;;163093:13;163073:17;;:33;163069:212;;;163176:18;;;;163069:212;;;163256:5;163243:18;;;;163069:212;162832:464;;163324:17;:33;;;162756:613;163381:14;163428:19;163412:13;:35;163408:777;;;163549:27;;163654:150;163687:116;124146:3;163687:90;163701:75;163740:1;-1:-1:-1;;163703:17:0;;163702:35;;:39;163549:27;163701:45;:75::i;:::-;163687:9;;:90;:13;:90;:::i;:116::-;163654:28;:9;163668:13;163654:28;:13;:28;:::i;:150::-;163645:159;-1:-1:-1;163908:57:0;163926:38;:13;163944:19;163926:38;:17;:38;:::i;:::-;163908:13;;:57;:17;:57;:::i;:::-;163892:73;-1:-1:-1;164070:103:0;164084:88;124146:3;164084:62;164117:28;164084;:9;164098:13;164084:28;:13;:28;:::i;:88::-;164070:9;;:103;:13;:103;:::i;:::-;164058:115;;163408:777;;164256:65;164267:53;164300:19;164267:28;:13;164285:9;164267:28;:17;:28;:::i;:53::-;164256:6;;:65;:10;:65;:::i;:::-;164247:74;-1:-1:-1;164341:51:0;164374:17;164341:28;164247:74;164352:16;164341:28;:10;:28;:::i;:51::-;164332:60;161861:2563;-1:-1:-1;;;;;;;;161861:2563:0:o;166258:417::-;166474:14;;166442:29;166499:169;166523:23;166519:1;:27;166499:169;;;166568:88;166592:18;166611:1;166592:21;;;;;;;;;;;;;;166615;166638:17;166568:23;:88::i;:::-;166548:3;;166499:169;;174899:374;174970:12;;174946:21;175013:20;174970:12;175031:1;175013:20;:17;:20;:::i;:::-;174993:40;;175046:26;;:::i;:::-;-1:-1:-1;175075:32:0;;;;:21;:32;;;;;;;;175046:61;;;;;;;;;;;;;;;;;;;;;;;;;;175118:54;;175046:61;175118:14;:54::i;:::-;-1:-1:-1;175192:36:0;;;;:21;:36;;;;;175185:43;;;;;;;;;175241:12;:24;174899:374::o;169871:852::-;170069:7;;170102:23;170098:69;;-1:-1:-1;170150:1:0;;-1:-1:-1;170150:1:0;170142:13;;170098:69;170179:23;170205:51;170237:18;170205:27;:15;170225:6;170205:27;:19;:27;:::i;:51::-;170329:22;170354:23;;;:10;:23;;;;;:38;;;170179:77;;-1:-1:-1;170407:18:0;;170403:193;;170460:124;170498:71;121911:3;170498:47;170530:14;170498:27;:6;170509:15;170498:27;:10;:27;:::i;:71::-;170460:15;;:124;:19;:124;:::i;:::-;170442:142;;170403:193;170608:24;170635:27;:6;170646:15;170635:27;:10;:27;:::i;:::-;170681:15;;-1:-1:-1;170608:54:0;;-1:-1:-1;;;169871:852:0;;;;;;;;:::o;6978:342::-;7059:8;;7038:4;;7055:31;;-1:-1:-1;7081:5:0;7074:12;;7055:31;7135:11;;;;7198:13;;7099:11;7190:22;;4104:4;7239:24;;7235:55;;;7285:5;7278:12;;;;;;7235:55;-1:-1:-1;7308:4:0;;6978:342;-1:-1:-1;;;6978:342:0:o;9786:422::-;9868:8;;9847:4;;9864:27;;-1:-1:-1;9890:1:0;9883:8;;9864:27;9904:10;9917:1;9904:14;;9929:12;9958:27;9973:4;:11;;;9958:14;:27::i;:::-;9944:11;;;;10024:8;;9944:41;;;;-1:-1:-1;10010:22:0;10043:133;10060:6;10050:7;:16;10043:133;;;10102:20;10114:7;10102:11;:20::i;:::-;10157:7;;;;;10092:30;;;;10043:133;;;-1:-1:-1;10195:5:0;;9786:422;-1:-1:-1;;;9786:422:0:o;11642:552::-;11780:13;;11701:4;;11772:22;;4010:4;11821:26;;11817:369;;;11870:1;11863:8;;;;;11817:369;4057:4;11891:25;;;:83;;-1:-1:-1;4104:4:0;11921:25;;;;;:52;;-1:-1:-1;4151:4:0;11950:23;;11921:52;11887:299;;;11996:1;11989:8;;;;;11887:299;4104:4;12017:24;;12013:173;;;-1:-1:-1;;12082:35:0;;-1:-1:-1;12075:42:0;;12013:173;-1:-1:-1;;12153:33:0;;-1:-1:-1;12146:40:0;;10260:1327;10418:13;;10316:4;;;;10410:22;;4010:4;10459:26;;10455:1098;;;10510:1;10500:11;;10455:1098;;;4057:4;10541:25;;10537:1016;;;-1:-1:-1;;10591:30:0;;;-1:-1:-1;10537:1016:0;;;4104:4;10643:24;;10639:914;;;10738:4;10731:5;10727:16;10818:1;10810:6;10806:14;10796:24;;10976:7;10972:2;10968:16;10963:3;10959:26;10950:6;10944:13;10940:46;11074:1;11065:7;11061:15;11052:7;11048:29;11037:40;;10693:399;;;;;4151:4;11124:23;;11120:433;;;-1:-1:-1;;11174:28:0;;;-1:-1:-1;11120:433:0;;;11301:4;11294:5;11290:16;11346:1;11338:6;11334:14;11324:24;;11419:7;11415:2;11411:16;11406:3;11402:26;11393:6;11387:13;11383:46;11524:1;11515:7;11511:15;11502:7;11498:29;11487:40;;11256:286;;;-1:-1:-1;11572:7:0;10260:1327;-1:-1:-1;;10260:1327:0:o;168485:391::-;168699:7;168744:45;;;168807:61;122005:6;168807:39;168744:45;168826:19;168807:39;:18;:39;:::i;169107:756::-;169304:26;169333:36;:15;169353;169333:36;:19;:36;:::i;:::-;169304:65;;169381:23;169406:24;169447:90;169480:11;169493:15;169510:6;169518:18;169447:32;:90::i;:::-;169380:157;;-1:-1:-1;169380:157:0;-1:-1:-1;169554:20:0;;169550:158;;169634:23;;;;:10;:23;;;;;:40;;;:62;;169679:16;169634:62;:44;:62;:::i;:::-;169591:23;;;;:10;:23;;;;;:40;;:105;169550:158;169724:19;;169720:136;;169793:23;;;;:10;:23;;;;;:30;;;:51;;169828:15;169793:51;:34;:51;:::i;:::-;169760:23;;;;:10;:23;;;;;:30;;:84;169107:756;;;;;;;:::o;168884:215::-;168978:10;;168974:118;;169038:23;;;;:10;:23;;;;;:30;;;:42;;169073:6;169038:42;:34;:42;:::i;:::-;169005:23;;;;:10;:23;;;;;:30;;:75;168884:215;;:::o;1265:106::-;1323:7;1354:1;1350;:5;:13;;1362:1;1350:13;;;-1:-1:-1;1358:1:0;;1343:20;-1:-1:-1;1265:106:0:o;132244:45525::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;132244:45525:0;-1:-1:-1;;;;;132244:45525:0;;;;;;;;;;;-1:-1:-1;132244:45525:0;;;;;;;-1:-1:-1;132244:45525:0;;;-1:-1:-1;132244:45525:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;;132244:45525:0;;;;;;;;;;;;;;;;;;;;;;;;
Swarm Source
bzzr://58be6eb435b22b31280540e2326580f39ea0fe929cd1983b8a5ad5d82a779e67
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.