Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 9 from a total of 9 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Validator Stake | 23073087 | 217 days ago | IN | 0 ETH | 0.00000672 | ||||
| Validator Stake | 23054747 | 220 days ago | IN | 0 ETH | 0.00000731 | ||||
| Validator Stake | 23028216 | 224 days ago | IN | 0 ETH | 0.00002764 | ||||
| Validator Stake | 23006274 | 227 days ago | IN | 0 ETH | 0.00000555 | ||||
| Validator Stake | 22995449 | 228 days ago | IN | 0 ETH | 0.00002555 | ||||
| Validator Stake | 22957292 | 234 days ago | IN | 0 ETH | 0.00007206 | ||||
| Validator Stake | 22747818 | 263 days ago | IN | 0 ETH | 0.00007864 | ||||
| Validator Stake | 22721614 | 267 days ago | IN | 0 ETH | 0.0000732 | ||||
| Initialize | 13045788 | 1666 days ago | IN | 0 ETH | 0.01679273 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract contains unverified libraries: Merkle
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
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2021-06-14
*/
// 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 hamdi.allam97@gmail.com
* 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
) public 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 tr vbmansfer 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
);
}
}
// 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 {
_withdrawAndTransferReward(to);
_withdrawAndTransferReward(from);
// move shares to recipient
super._transfer(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)) {}
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");
}
updateTimeline(amount, 0, 0);
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);
signerToValidator[currentSigner] = INCORRECT_VALIDATOR_ID;
signerToValidator[signer] = validatorId;
validators[validatorId].signer = signer;
_updateSigner(currentSigner, 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 _updateSigner(address prevSigner, address newSigner) internal {
_removeSigner(prevSigner);
_insertSigner(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
Contract ABI
API[{"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
60806040526023805460ff1916905534801561001a57600080fd5b5060008054610100600160a81b0319168155600180546001600160a01b0319163317908190556040516001600160a01b039190911691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3615d5580620000866000396000f3fe608060405234801561001057600080fd5b50600436106106235760003560e01c80637d66975211610336578063b1d23f02116101c3578063e6692f491161010f578063f5e95acb116100ad578063f8a3176c11610087578063f8a3176c14611522578063fb1ef52c1461152a578063fba58f3414611553578063fc0c546a1461155b57610623565b8063f5e95acb14611493578063f771fc87146114fd578063f83d08ba1461151a57610623565b8063f24ccbfe116100e9578063f24ccbfe1461139b578063f28699fa146113a3578063f2fde38b146113c2578063f41a9642146113e857610623565b8063e6692f491461133b578063e8afa8e814611358578063eceec1d31461137e57610623565b8063cf3090121161017c578063d86d53e711610156578063d86d53e7146112eb578063dcd962b214611308578063e568959a1461132b578063e59ee0c61461133357610623565b8063cf309012146112a7578063d6de07d0146112af578063d7f5549d146112ce57610623565b8063b1d23f02146111e4578063b65de35e14611207578063bc8756a914611224578063c710e92214611256578063cbf383d514611282578063cd6b83881461129f57610623565b8063987ab9db11610282578063a440ab1e1161023b578063a69df4b511610215578063a69df4b5146111a0578063a7ab6961146111a8578063a8dc889b146111b0578063b184be81146111b857610623565b8063a440ab1e146110f8578063a476907114611115578063a68548771461111d57610623565b8063987ab9db1461106257806399d18f6f1461106a5780639a8a62431461108d5780639b33f434146110955780639ddbbf85146110b25780639ff11500146110d557610623565b8063883b455f116102ef578063900cf0cf116102c9578063900cf0cf14611018578063914601491461102057806391f1a3a51461103d5780639342c8f41461104557610623565b8063883b455f146110005780638da5cb5b146110085780638f32d59b1461101057610623565b80637d66975214610f8b5780637ed4b27c14610f935780637f4b432314610fb05780637f952d9514610fcd578063817b1cd214610fd5578063858a7c0314610fdd57610623565b8063451b5985116104b45780635e47655f116104005780637060054d116103b957806377939d101161039357806377939d1014610f4d57806378f84a4414610f555780637b10399914610f7b5780637c7eaf1a14610f8357610623565b80637060054d14610f35578063715018a614610f3d5780637667180814610f4557610623565b80635e47655f14610d7357806360c8d12214610de15780636352211e14610e0a5780636365679814610e2757806368cb812a14610e535780636901b25314610f0357610623565b806352b8115d1161046d5780635508d8e1116104475780635508d8e114610d3e57806356342d8c14610d465780635aa6e67514610d635780635ab1bd5314610d6b57610623565b806352b8115d14610bd75780635325e14414610c6f57806354b8c60114610d3657610623565b8063451b598514610a9657806348ab8b2a14610a9e5780634b341aed14610ada5780634e3c83f114610b005780634fd101d714610b085780634fdd20f114610b1057610623565b806325316411116105735780632fa9d18b1161052c57806335aa2e441161050657806335aa2e44146109925780633862da0b14610a4b57806339610f7814610a7157806341b3d18514610a8e57610623565b80632fa9d18b146108f357806331c2273b14610982578063342745861461098a57610623565b8063253164111461079b57806325726df2146107a35780632649263a146107d957806328cc4e411461080a5780632cf44a43146108355780632e17de78146108d657610623565b8063174e6832116105e05780631ae4818f116105ba5780631ae4818f146107175780631dd6b9b11461073b5780631e9b12ef146107585780632079fb9a1461077e57610623565b8063174e6832146106cc578063178c2c83146106f257806317c2b9101461070f57610623565b806306cfb10414610628578063078a13b1146106475780630cccfc58146106855780630e15561a1461069f5780630ebb172a146106a757806316827b1b146106af575b600080fd5b6106456004803603602081101561063e57600080fd5b5035611563565b005b6106456004803603608081101561065d57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060013516611570565b61068d6115e8565b60408051918252519081900360200190f35b61068d6115ee565b61068d6115f4565b610645600480360360208110156106c557600080fd5b50356115fa565b61068d600480360360208110156106e257600080fd5b50356001600160a01b0316611683565b6106456004803603602081101561070857600080fd5b503561170d565b61068d61199a565b61071f6119a0565b604080516001600160a01b039092168252519081900360200190f35b6106456004803603602081101561075157600080fd5b50356119af565b6106456004803603602081101561076e57600080fd5b50356001600160a01b03166119bc565b61071f6004803603602081101561079457600080fd5b50356119f9565b61068d611a20565b6107c0600480360360208110156107b957600080fd5b5035611a26565b6040805192835260208301919091528051918290030190f35b6107f6600480360360208110156107ef57600080fd5b5035611a3f565b604080519115158252519081900360200190f35b6106456004803603606081101561082057600080fd5b50803590602081013590604001351515611a7a565b6106456004803603602081101561084b57600080fd5b810190602081018135600160201b81111561086557600080fd5b82018360208201111561087757600080fd5b803590602001918460208302840111600160201b8311171561089857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611c90945050505050565b610645600480360360208110156108ec57600080fd5b5035611cb8565b61068d600480360360a081101561090957600080fd5b8135916020810135916040820135916001600160a01b036060820135169181019060a081016080820135600160201b81111561094457600080fd5b82018360208201111561095657600080fd5b803590602001918460608302840111600160201b8311171561097757600080fd5b509092509050611d7a565b61071f61208b565b61068d61209a565b6109af600480360360208110156109a857600080fd5b50356120a0565b604051808e81526020018d81526020018c81526020018b81526020018a8152602001896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b03168152602001876003811115610a0d57fe5b60ff1681526020018681526020018581526020018481526020018381526020018281526020019d505050505050505050505050505060405180910390f35b61068d60048036036020811015610a6157600080fd5b50356001600160a01b0316612111565b61068d60048036036020811015610a8757600080fd5b5035612123565b61068d612163565b61068d612169565b61064560048036036080811015610ab457600080fd5b508035906001600160a01b0360208201358116916040810135909116906060013561216f565b61068d60048036036020811015610af057600080fd5b50356001600160a01b03166121f6565b61068d61232d565b61068d612333565b610645600480360360a0811015610b2657600080fd5b6001600160a01b0382351691602081013591604082013591606081013515159181019060a081016080820135600160201b811115610b6357600080fd5b820183602082011115610b7557600080fd5b803590602001918460018302840111600160201b83111715610b9657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612339945050505050565b610645600480360360c0811015610bed57600080fd5b6001600160a01b038235169160208101359160408201359160608101359160808201351515919081019060c0810160a0820135600160201b811115610c3157600080fd5b820183602082011115610c4357600080fd5b803590602001918460018302840111600160201b83111715610c6457600080fd5b5090925090506123fa565b610c8c60048036036020811015610c8557600080fd5b5035612519565b60405180868152602001858152602001846001600160a01b03166001600160a01b031681526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610cf7578181015183820152602001610cdf565b50505050905090810190601f168015610d245780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b6107f66125df565b61068d6125e8565b61071f60048036036020811015610d5c57600080fd5b50356125ee565b61071f61260c565b61071f612620565b61068d60048036036020811015610d8957600080fd5b810190602081018135600160201b811115610da357600080fd5b820183602082011115610db557600080fd5b803590602001918460018302840111600160201b83111715610dd657600080fd5b509092509050612630565b61064560048036036060811015610df757600080fd5b5080359060208101359060400135612951565b61071f60048036036020811015610e2057600080fd5b50356129ba565b61064560048036036040811015610e3d57600080fd5b506001600160a01b038135169060200135612a06565b61064560048036036060811015610e6957600080fd5b813591602081013591810190606081016040820135600160201b811115610e8f57600080fd5b820183602082011115610ea157600080fd5b803590602001918460018302840111600160201b83111715610ec257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612a1b945050505050565b6107f660048036036060811015610f1957600080fd5b50803590602081013590604001356001600160a01b0316612bce565b61068d612c6b565b610645612c71565b61068d612ccc565b61068d612cd2565b61068d60048036036020811015610f6b57600080fd5b50356001600160a01b0316612cd8565b61071f612cea565b61068d612cf9565b61068d612cff565b61068d60048036036020811015610fa957600080fd5b5035612d05565b61068d60048036036020811015610fc657600080fd5b5035612d5c565b61068d612d71565b61068d612d77565b61064560048036036040811015610ff357600080fd5b5080359060200135612d7d565b61071f612dc3565b61071f612dd7565b6107f6612de6565b61068d612e29565b6106456004803603602081101561103657600080fd5b5035612e2f565b61068d612e46565b6106456004803603602081101561105b57600080fd5b5035612e4c565b61071f612e69565b6106456004803603604081101561108057600080fd5b5080359060200135612e78565b61068d612ede565b610645600480360360208110156110ab57600080fd5b5035612ee4565b610645600480360360408110156110c857600080fd5b5080359060200135612fa0565b610645600480360360408110156110eb57600080fd5b5080359060200135613006565b6106456004803603602081101561110e57600080fd5b503561309a565b61068d6130b1565b6106456004803603608081101561113357600080fd5b813591602081013591604082013515159190810190608081016060820135600160201b81111561116257600080fd5b82018360208201111561117457600080fd5b803590602001918460018302840111600160201b8311171561119557600080fd5b5090925090506130b7565b61064561316f565b61068d613181565b61068d613187565b610645600480360360408110156111ce57600080fd5b506001600160a01b03813516906020013561318d565b610645600480360360408110156111fa57600080fd5b508035906020013561319f565b61068d6004803603602081101561121d57600080fd5b50356131b2565b6107f66004803603606081101561123a57600080fd5b50803590602081013590604001356001600160a01b0316613200565b6106456004803603604081101561126c57600080fd5b50803590602001356001600160a01b0316613368565b6106456004803603602081101561129857600080fd5b5035613423565b61068d6134ac565b6107f66134b2565b610645600480360360208110156112c557600080fd5b503515156134bb565b61068d600480360360208110156112e457600080fd5b503561360d565b6106456004803603602081101561130157600080fd5b503561361f565b6106456004803603604081101561131e57600080fd5b5080359060200135613805565b61068d61386d565b6107c0613873565b6106456004803603602081101561135157600080fd5b503561387c565b6106456004803603602081101561136e57600080fd5b50356001600160a01b0316613938565b61068d6004803603602081101561139457600080fd5b50356139b8565b61071f6139ca565b610645600480360360208110156113b957600080fd5b503515156139d9565b610645600480360360208110156113d857600080fd5b50356001600160a01b03166139f4565b610645600480360360408110156113fe57600080fd5b81359190810190604081016020820135600160201b81111561141f57600080fd5b82018360208201111561143157600080fd5b803590602001918460018302840111600160201b8311171561145257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550613a0e945050505050565b61064560048036036101208110156114aa57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c082013581169160e08101358216916101009091013516613bfc565b6106456004803603602081101561151357600080fd5b5035613d9f565b610645613dba565b61071f613dca565b6106456004803603606081101561154057600080fd5b5080359060208101359060400135613dd9565b61068d613ef4565b61071f613efa565b61156b613f09565b600f55565b611578613f09565b61158181613f57565b61158a57600080fd5b60238054610100600160a81b0319169055602580546001600160a01b03199081166001600160a01b03938416179091556006805482169583169590951790945560058054851693821693909317909255600780549093169116179055565b60155481565b60135481565b60085481565b611602613f09565b8061160c57600080fd5b60055460105460408051630f1980a560e41b8152600481018590526024810192909252516001600160a01b039092169163f1980a509160448082019260009290919082900301818387803b15801561166357600080fd5b505af1158015611677573d6000803e3d6000fd5b50505060109190915550565b60065460408051632f745c5960e01b81526001600160a01b038481166004830152600060248301819052925192931691632f745c5991604480820192602092909190829003018186803b1580156116d957600080fd5b505afa1580156116ed573d6000803e3d6000fd5b505050506040513d602081101561170357600080fd5b505190505b919050565b8061171781613f76565b60026000838152601a6020526040902060060154600160a01b900460ff16600381111561174057fe5b1461177f576040805162461bcd60e51b815260206004820152600a602482015269139bdd081a985a5b195960b21b604482015290519081900360640190fd5b6000828152601a6020526040902060030154156117d7576040805162461bcd60e51b8152602060048201526011602482015270416c726561647920756e7374616b696e6760781b604482015290519081900360640190fd5b6009546000838152601a6020526040902060040154811015611839576040805162461bcd60e51b8152602060048201526016602482015275125b98dbdb5c1b195d19481a985a5b081c195c9a5bd960521b604482015290519081900360640190fd5b6000838152601a6020526040902054600c5481101561185757600080fd5b6000848152601a60205260409020600601546001600160a01b031680156118cc57806001600160a01b031663a69df4b56040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156118b357600080fd5b505af11580156118c7573d6000803e3d6000fd5b505050505b6000858152601a60205260409020600a01546118fc906118f390849063ffffffff61400016565b60016000614012565b6000858152601a602052604080822060068101805460ff60a01b1916600160a01b1790556005908101549054825163f92ec5af60e01b8152600481018a90526001600160a01b039283166024820181905293519394929091169263f92ec5af9260448084019391929182900301818387803b15801561197a57600080fd5b505af115801561198e573d6000803e3d6000fd5b50505050505050505050565b60175481565b6007546001600160a01b031681565b6119b7613f09565b600955565b6119c4613f09565b6001600160a01b0381166119d757600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60268181548110611a0657fe5b6000918252602090912001546001600160a01b0316905081565b600e5481565b601e602052600090815260409020805460019091015482565b6000818152601a6020526040812060068101548154600390920154600954611a7493600160a01b90930460ff169291906140cd565b92915050565b611a82614105565b82611a8c81613f76565b6000848152601a602052604090206003015415611adf576040805162461bcd60e51b815260206004820152600c60248201526b4e6f2072657374616b696e6760a01b604482015290519081900360640190fd5b8215611af057611af0333085614146565b611af984614218565b8115611b4c576000848152601a60205260409020600190810154611b359190611b2990869063ffffffff61400016565b9063ffffffff61422716565b6000858152601a6020526040902060019081015592505b601154600090611b62908563ffffffff61400016565b60118190556000868152601a6020526040902054909150611b89908563ffffffff61400016565b6000868152601a6020526040812091909155611ba790859080614012565b6005546040805163532e19a960e01b81526004810188905290516001600160a01b039092169163532e19a99160248082019260009290919082900301818387803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b50506005546000888152601a6020526040808220548151631585a9f360e21b8152600481018c905260248101919091526044810187905290516001600160a01b039093169450635616a7cc93506064808201939182900301818387803b158015611c7157600080fd5b505af1158015611c85573d6000803e3d6000fd5b505050505050505050565b611c98612de6565b611ca157600080fd5b8051611cb4906026906020840190615bc9565b5050565b80611cc281613f76565b600082815260208052604090205415611cda57600080fd5b6000828152601a602052604090206006810154600290910154600160a01b90910460ff169015801590611d1c57506000838152601a6020526040902060030154155b8015611d4857506001816003811115611d3157fe5b1480611d4857506002816003811115611d4657fe5b145b611d5157600080fd5b600954600090611d6890600163ffffffff61400016565b9050611d74848261423c565b50505050565b6002546000906001600160a01b03163314611d9457600080fd5b600954601d546000908190611da7615c2e565b6026546040805191840180835260208082028401019091528015611dd5578160200160208202803883390190505b5060408083019190915260268054825160208083028201810190945281815292830182828015611e2e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611e10575b50505050506060820152600060208201526026546080820152611e4f615c5d565b6026546040805191850180835260208082028401019091528015611e7d578160200160208202803883390190505b50602082015260005b8881101561204c576000611ed48e8c8c85818110611ea057fe5b90506060020160038060200260405190810160405280929190826003602002808284376000920191909152506143c0915050565b9050856001600160a01b0316816001600160a01b03161415611ef65750612044565b856001600160a01b0316816001600160a01b03161015611f16575061204c565b6001600160a01b0381166000908152601b6020908152604080832054808452601a909252909120805460068201546003909201548087529091600160a01b900460ff1690611f6890829084908e6140cd565b15611ff3576000838152601a60205260409020600a01549398508893611fa7908390611f9b908d9063ffffffff61400016565b9063ffffffff61400016565b8651909a5015611fe157828660200151876040015181518110611fc657fe5b60209081029190910101526040860180516001019052611fee565b611feb87856144c3565b96505b61203f565b600281600381111561200157fe5b141561203f5782876040015188600001518151811061201c57fe5b602090810291909101810191909152875160019081018952908801805190910190525b505050505b600101611e86565b506120588260006144c3565b915061207a8d8b878e86604001518760000151876020015188604001516145a0565b9d9c50505050505050505050505050565b6006546001600160a01b031681565b60165481565b601a60205260009081526040902080546001820154600283015460038401546004850154600586015460068701546007880154600889015460098a0154600a8b0154600b909b0154999a98999798969795966001600160a01b039586169695851695600160a01b90950460ff16948d565b601b6020526000908152604090205481565b60008061212f83614708565b6000858152601a602052604090206009015490925061215c9150600190611b29908463ffffffff61400016565b9392505050565b600c5481565b60295481565b612177613f09565b6000848152601a60205260409020600601546001600160a01b03168061219c57600080fd5b6040805163abf59fc960e01b81526001600160a01b03868116600483015285811660248301526044820185905291519183169163abf59fc99160648082019260009290919082900301818387803b158015611c7157600080fd5b60006001600160a01b03821615806122845750600654604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b15801561225657600080fd5b505afa15801561226a573d6000803e3d6000fd5b505050506040513d602081101561228057600080fd5b5051155b1561229157506000611708565b60065460408051632f745c5960e01b81526001600160a01b0385811660048301526000602483018190529251601a949190911691632f745c59916044808301926020929190829003018186803b1580156122ea57600080fd5b505afa1580156122fe573d6000803e3d6000fd5b505050506040513d602081101561231457600080fd5b5051815260208101919091526040016000205492915050565b600f5481565b60105481565b612341614105565b60105461234c612d71565b1061238e576040805162461bcd60e51b815260206004820152600d60248201526c6e6f206d6f726520736c6f747360981b604482015290519081900360640190fd5b600c548410156123da576040805162461bcd60e51b81526020600482015260126024820152711b9bdd08195b9bdd59da0819195c1bdcda5d60721b604482015290519081900360640190fd5b6123e685338587614784565b6123f28585848461486e565b505050505050565b33301461243c576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6124498788886000614784565b6124558560095461423c565b600061249988868686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061486e92505050565b6005546040805163e12ab1af60e01b815260048101849052602481018a90526044810189905290519293506001600160a01b039091169163e12ab1af9160648082019260009290919082900301818387803b1580156124f757600080fd5b505af115801561250b573d6000803e3d6000fd5b505050505050505050505050565b60208080526000918252604091829020805460018083015460028085015460038601805489516101009682161596909602600019011692909204601f8101889004880285018801909852878452939691956001600160a01b03851695600160a01b90950460ff16949392908301828280156125d55780601f106125aa576101008083540402835291602001916125d5565b820191906000526020600020905b8154815290600101906020018083116125b857829003601f168201915b5050505050905085565b60195460ff1681565b60125481565b6000908152601a60205260409020600601546001600160a01b031690565b60005461010090046001600160a01b031681565b6004546001600160a01b03165b90565b6004805460408051631ab0168360e31b8152905160009333936001600160a01b03169263d580b4189281830192602092829003018186803b15801561267457600080fd5b505afa158015612688573d6000803e3d6000fd5b505050506040513d602081101561269e57600080fd5b50516001600160a01b0316146126ef576040805162461bcd60e51b81526020600482015260116024820152702737ba1039b630b9b41036b0b730b3b2b960791b604482015290519081900360640190fd5b606061273861273385858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250614c7b92505050565b614ca0565b90506000806000805b845181101561292557606061276886838151811061275b57fe5b6020026020010151614ca0565b905060006127898260008151811061277c57fe5b6020026020010151614d71565b905061279481614218565b60006127a68360018151811061277c57fe5b90506127b8858263ffffffff61400016565b6000838152601a60205260409020600601549095506001600160a01b03168015612886576000838152601a602090815260408083208054600a9091015482516306cbb60560e41b8152600481019290925260248201526044810186905290516001600160a01b03851692636cbb6050926064808201939182900301818787803b15801561284457600080fd5b505af1158015612858573d6000803e3d6000fd5b505050506040513d602081101561286e57600080fd5b50519050612882838263ffffffff61422716565b9250505b6000838152601a60205260408120546128a5908463ffffffff61422716565b6000858152601a602052604090208190559050806128ce576128c98460095461423c565b612914565b6128eb856002815181106128de57fe5b6020026020010151614dd1565b156129145761290b6128fe856001614e05565b899063ffffffff61400016565b60019099019897505b505060019093019250612741915050565b612946612938838563ffffffff61400016565b600003856000036000614012565b509695505050505050565b612959613f09565b60255460408051602481018690526044810185905260648082018590528251808303909101815260849091019091526020810180516001600160e01b0316633064689160e11b1790526129b5916001600160a01b031690614f4f565b505050565b600654604080516331a9108f60e11b81526004810184905290516000926001600160a01b031691636352211e916024808301926020929190829003018186803b1580156116d957600080fd5b612a0e614105565b611cb48233836000614784565b60408051336020808301919091528183018690528251808303840181526060830193849052805190820120601754631b23d15760e21b909452606483018181526084840187905260a48401859052608060c48501908152865160e4860152865173540bde6642a8cb547a6887934044e465914112d096636c8f455c9694958a9591948a9490939092610104019185019080838360005b83811015612ac9578181015183820152602001612ab1565b50505050905090810190601f168015612af65780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038186803b158015612b1657600080fd5b505af4158015612b2a573d6000803e3d6000fd5b505050506040513d6020811015612b4057600080fd5b5051612b85576040805162461bcd60e51b815260206004820152600f60248201526e2bb937b7339030b1b190383937b7b360891b604482015290519081900360640190fd5b336000908152601f6020526040812054612ba690859063ffffffff61422716565b9050612bb23382614f77565b336000818152601f60205260409020859055611d749082614ff6565b600083612bda816150bb565b600354604080516323b872dd60e01b81526001600160a01b03868116600483015230602483015260448201889052915191909216916323b872dd9160648083019260209291908290030181600087803b158015612c3657600080fd5b505af1158015612c4a573d6000803e3d6000fd5b505050506040513d6020811015612c6057600080fd5b505195945050505050565b600a5481565b612c79612de6565b612c8257600080fd5b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b60095481565b60185481565b601f6020526000908152604090205481565b6004546001600160a01b031681565b602a5481565b600b5481565b600081612d11816150bb565b612d1a83614218565b6000838152601a6020526040812060090154612d3d90600163ffffffff61422716565b6000858152601a60205260409020600160099091015592505050919050565b6000908152601a60205260409020600a015490565b601d5490565b60115481565b81612d87816150bb565b6000838152601a60205260409020600a0154612da9908363ffffffff61422716565b6000938452601a6020526040909320600a01929092555050565b60235461010090046001600160a01b031681565b6001546001600160a01b031690565b604080517f6d617469632e6e6574776f726b2e70726f78792e6f776e6572000000000000008152905190819003601901902054336001600160a01b039091161490565b60095490565b612e37613f09565b612e438160095461423c565b50565b60275481565b80612e5681613f76565b612e5f82614218565b611cb48233615129565b6002546001600160a01b031681565b612e80614105565b602554604080516024810185905260448101849052306064808301919091528251808303909101815260849091019091526020810180516001600160e01b031663561ad5c960e11b179052611cb4916001600160a01b031690614f4f565b60225481565b612eec613f09565b6005546016546040805163a3b1d8cb60e01b8152600481018590526024810192909252516001600160a01b039092169163a3b1d8cb9160448082019260009290919082900301818387803b158015612f4357600080fd5b505af1158015612f57573d6000803e3d6000fd5b505050506064811115612f9b576040805162461bcd60e51b8152602060048201526007602482015266746f6f2062696760c81b604482015290519081900360640190fd5b601655565b612fa8612de6565b612fb157600080fd5b602554604080516024810185905260448082018590528251808303909101815260649091019091526020810180516001600160e01b0316639ddbbf8560e01b179052611cb4916001600160a01b031690614f4f565b81613010816150bb565b60008213156130695760195460ff16613069576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b61307582600080614012565b6000821261308c5761308783836151ea565b6129b5565b6129b5838360001902612d7d565b6130a2613f09565b806130ac57600080fd5b600e55565b601c5490565b6130bf614105565b6025546040516024810187815260448201879052851515606483015260806084830190815260a48301859052613168936001600160a01b03169263a685487760e01b928a928a928a928a928a9260c40184848082843760008184015260408051601f19601f9093018316909401848103909201845252506020810180516001600160e01b03199a909a166001600160e01b03909a169990991790985250614f4f95505050505050565b5050505050565b613177613f09565b61317f615225565b565b60085490565b60245481565b613195613f09565b611cb48282614ff6565b6131a7613f09565b600c91909155600d55565b6000818152601a602052604081206003015481906131d7576131d383614708565b5090505b6000838152601a6020526040902060019081015461215c9190611b29908463ffffffff61400016565b6000838152601a60205260408120600601546001600160a01b031633148061329f57506004805460408051631ab0168360e31b8152905133936001600160a01b039093169263d580b41892808201926020929091829003018186803b15801561326857600080fd5b505afa15801561327c573d6000803e3d6000fd5b505050506040513d602081101561329257600080fd5b50516001600160a01b0316145b6132de576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6003546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018790529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561333457600080fd5b505af1158015613348573d6000803e3d6000fd5b505050506040513d602081101561335e57600080fd5b5051949350505050565b613370613f09565b306001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156133b357600080fd5b505afa1580156133c7573d6000803e3d6000fd5b505050506040513d60208110156133dd57600080fd5b50516001600160a01b0316146133f257600080fd5b6000918252601a602052604090912060060180546001600160a01b0319166001600160a01b03909216919091179055565b61342b613f09565b8061343557600080fd5b600554600b5460408051632dbe9d3160e21b8152600481018590526024810192909252516001600160a01b039092169163b6fa74c49160448082019260009290919082900301818387803b15801561348c57600080fd5b505af11580156134a0573d6000803e3d6000fd5b505050600b9190915550565b60145481565b60005460ff1681565b336000908152601b6020908152604080832054808452601a9092529091206006810154815460039092015460095461350093600160a01b90930460ff169291906140cd565b613541576040805162461bcd60e51b815260206004820152600d60248201526c3737ba103b30b634b230ba37b960991b604482015290519081900360640190fd5b6000818152601a60205260409020600601546001600160a01b0316806135a7576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b604080516303dd464160e51b8152841515600482015290516001600160a01b03831691637ba8c82091602480830192600092919082900301818387803b1580156135f057600080fd5b505af1158015613604573d6000803e3d6000fd5b50505050505050565b60216020526000908152604090205481565b8061362981613f76565b6000828152601a6020526040902060030154801580159061365f575060095460085461365c90839063ffffffff61400016565b11155b8015613692575060036000848152601a6020526040902060060154600160a01b900460ff16600381111561368f57fe5b14155b61369b57600080fd5b6000838152601a60205260408120546011549091906136c0908363ffffffff61422716565b601181905590506136d18533615129565b60065460408051630852cd8d60e31b81526004810188905290516001600160a01b03909216916342966c689160248082019260009290919082900301818387803b15801561371e57600080fd5b505af1158015613732573d6000803e3d6000fd5b5050506000868152601a6020526040812081815560048101919091556005810180546001600160a01b03191690556000197f584f46c60af19681376031579adb04a2416e54ee5505351c2a8435e3766026ea55600601805460ff60a01b1916600360a01b179055506137a43383614ff6565b6005546040805163ae2e26b160e01b815233600482015260248101889052604481018590526064810184905290516001600160a01b039092169163ae2e26b19160848082019260009290919082900301818387803b158015611c7157600080fd5b8161380f81613f76565b61381883614218565b602554604080516024810186905260448082018690528251808303909101815260649091019091526020810180516001600160e01b0316636e6cb15960e11b1790526129b5916001600160a01b031690614f4f565b60285481565b601c54601d5482565b613884613f09565b6000811161389157600080fd5b600554600a5460408051635071805360e11b8152600481018590526024810192909252516001600160a01b039092169163a0e300a69160448082019260009290919082900301818387803b1580156138e857600080fd5b505af11580156138fc573d6000803e3d6000fd5b505050600a82905550600881905561391b81600463ffffffff61523116565b60158190556009546139329163ffffffff61400016565b60185550565b613940612de6565b61394957600080fd5b6001600160a01b03811661395c57600080fd5b6002546040516001600160a01b038084169216907f211c9015fc81c0dbd45bd99f0f29fc1c143bfd53442d5ffd722bbbef7a887fe990600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000908152601a602052604090205490565b6005546001600160a01b031681565b6139e1613f09565b6019805460ff1916911515919091179055565b6139fc612de6565b613a0557600080fd5b612e4381615253565b81613a1881613f76565b6000613a23836152c2565b600954600f546000878152602160205260409020549293509091613a4c9163ffffffff61400016565b811015613a8e576040805162461bcd60e51b815260206004820152600b60248201526a139bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6000858152601a602090815260408083206005908101549054915163b80fbce560e01b8152600481018a81526001600160a01b039283166024830181905288841660448401526080606484019081528b5160848501528b519197949095169563b80fbce5958d9589958c958f95909460a490920192918601918190849084905b83811015613b26578181015183820152602001613b0e565b50505050905090810190601f168015613b535780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015613b7557600080fd5b505af1158015613b89573d6000803e3d6000fd5b5050506001600160a01b038083166000908152601b6020908152604080832060001990559287168083528383208b90558a8352601a90915291902060050180546001600160a01b031916909117905550613be3818461537b565b5060009485526021602052604090942093909355505050565b60235460ff1615613c45576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6023805460ff19166001179055613c5b81613f57565b613ca5576040805162461bcd60e51b8152602060048201526016602482015275185d58dd1a5bdb881a5b5c1b081a5b98dbdc9c9958dd60521b604482015290519081900360640190fd5b602580546001600160a01b03199081166001600160a01b038481169190911790925560008054610100600160a81b031916610100878516021790556004805482168c84161790556002805482168b84161790556003805482168a841617905560068054821689841617905560058054821688841617905560078054909116918616919091179055613d3582615253565b5050612000600855505060016009819055610376600a90815569044664c7bf6451f00000600b55670de0b6b3a7640000600c819055600d55610400600e556064600f55600760105560128290556108006015556016556019805460ff191690911790555050505050565b613da7613f09565b600954613932908263ffffffff61400016565b613dc2613f09565b61317f61538d565b6025546001600160a01b031681565b60078211613e22576040805162461bcd60e51b815260206004820152601160248201527024b73b30b634b21036b4b3b930ba34b7b760791b604482015290519081900360640190fd5b6000838152601a6020526040808220600601548151636e7ce59160e01b81523360048201526024810185905291516001600160a01b0390911692636e7ce591926044808201939182900301818387803b158015613e7e57600080fd5b505af1158015613e92573d6000803e3d6000fd5b5050506000838152601a6020526040808220600601548151632830728d60e21b81523360048201526024810186905291516001600160a01b03909116935063a0c1ca349260448084019391929182900301818387803b1580156135f057600080fd5b600d5481565b6003546001600160a01b031681565b60005461010090046001600160a01b0316331461317f5760405162461bcd60e51b8152600401808060200182810382526026815260200180615cfb6026913960400191505060405180910390fd5b60006001600160a01b038216613f6f57506000611708565b503b151590565b600654604080516331a9108f60e11b815260048101849052905133926001600160a01b031691636352211e916024808301926020929190829003018186803b158015613fc157600080fd5b505afa158015613fd5573d6000803e3d6000fd5b505050506040513d6020811015613feb57600080fd5b50516001600160a01b031614612e4357600080fd5b60008282018381101561215c57600080fd5b806140ab57600083131561403b57601c54614033908463ffffffff61400016565b601c5561405f565b600083121561405f57601c5461405b90600085900363ffffffff61422716565b601c555b600082131561408357601d5461407b908363ffffffff61400016565b601d55613087565b600082121561308757601d546140a390600084900363ffffffff61422716565b601d556129b5565b6000818152601e60205260409020805484018155600101805483019055505050565b600080841180156140e557508215806140e557508183115b80156140fc575060018560038111156140fa57fe5b145b95945050505050565b60005460ff161561317f576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b600354604080516323b872dd60e01b81526001600160a01b038681166004830152858116602483015260448201859052915191909216916323b872dd9160648083019260209291908290030181600087803b1580156141a457600080fd5b505af11580156141b8573d6000803e3d6000fd5b505050506040513d60208110156141ce57600080fd5b50516129b5576040805162461bcd60e51b81526020600482015260146024820152731d1c985b9cd9995c88199c9bdb4819985a5b195960621b604482015290519081900360640190fd5b612e438160245460245461539c565b60008282111561423657600080fd5b50900390565b61424582614218565b6000828152601a60205260408120549061425e846129ba565b6000858152601a6020526040902060038101859055600a810154600690910154919250906001600160a01b031680156142e557806001600160a01b031663f83d08ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156142cc57600080fd5b505af11580156142e0573d6000803e3d6000fd5b505050505b6000868152601a6020526040902060050154614309906001600160a01b031661543d565b6143138684615129565b60006009548611156143255785614328565b60005b905061433c83860160000360001983614012565b60055460408051635e04d48360e01b81526001600160a01b038781166004830152602482018b9052604482018a90526064820189905291519190921691635e04d48391608480830192600092919082900301818387803b15801561439f57600080fd5b505af11580156143b3573d6000803e3d6000fd5b5050505050505050505050565b805160208201516040830151600092919060ff167f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156144085760009350505050611a74565b601b8160ff16101561441857601b015b8060ff16601b1415801561443057508060ff16601c14155b156144415760009350505050611a74565b60408051600080825260208083018085528a905260ff85168385015260608301879052608083018690529251909260019260a080820193601f1981019281900390910190855afa158015614499573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166144b957600080fd5b9695505050505050565b6144cb615c2e565b8260800151836020015110801561450f5750816001600160a01b031683606001518460200151815181106144fb57fe5b60200260200101516001600160a01b031614155b1561459057601b6000846060015185602001518151811061452c57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054836040015184600001518151811061456957fe5b602090810291909101810191909152835160019081018552908401805190910190526144cb565b5050602081018051600101905290565b601c546000906145cd6001611f9b60036145c185600263ffffffff61554716565b9063ffffffff61523116565b881015614617576040805162461bcd60e51b8152602060048201526013602482015272322f332b31206e6f6e2d6d616a6f726974792160681b604482015290519081900360640190fd5b60006146248b8a8461556e565b9050600061464260646145c16016548561554790919063ffffffff16565b6001600160a01b038c166000908152601b6020908152604080832054808452601a90925290912060018101549293509091614683908463ffffffff61400016565b600182015560178b905560006146d06146c18e6145c16a084595161401484a0000006146b58a8a63ffffffff61422716565b9063ffffffff61554716565b6024549063ffffffff61400016565b90506146dd8b8b836156c2565b60248190556146ed8989836156c2565b6146f56156f6565b50929d9c50505050505050505050505050565b6000818152601a602052604081208054600a90910154829190829061473490839063ffffffff61400016565b6000868152601a60205260409020600b0154602454919250900361477886846147726a084595161401484a0000006145c1868863ffffffff61554716565b8561576b565b94509450505050915091565b600d548210156147cb576040805162461bcd60e51b815260206004820152600d60248201526c199959481d1bdbc81cdb585b1b609a1b604482015290519081900360640190fd5b6147e583306147e0858563ffffffff61400016565b614146565b6022546147f8908363ffffffff61400016565b6022556005546040805163a449d79560e01b81526001600160a01b038781166004830152602482018690529151919092169163a449d79591604480830192600092919082900301818387803b15801561485057600080fd5b505af1158015614864573d6000803e3d6000fd5b5050505050505050565b60008061487a836152c2565b600954601254600554601154939450919290916001600160a01b0316906000906148aa908a63ffffffff61400016565b905080601181905550604051806101a001604052808a8152602001600181526020018581526020016000815260200160008152602001866001600160a01b03168152602001896148fb576000614987565b600754600480546040805163d4ad267360e01b81529283018990526001600160a01b03888116602485015291821660448401525192169163d4ad2673916064808201926020929091908290030181600087803b15801561495a57600080fd5b505af115801561496e573d6000803e3d6000fd5b505050506040513d602081101561498457600080fd5b50515b6001600160a01b031681526020016001815260006020808301829052604080840183905260016060808601829052608080870186905260245460a0978801528a8652601a855294839020875181559387015191840191909155908501516002830155840151600380830191909155918401516004820155918301516005830180546001600160a01b039283166001600160a01b03199182161790915560c08501516006850180549190931691161780825560e08501519260ff60a01b1990911690600160a01b908490811115614a5957fe5b0217905550610100820151600782015561012082015160088201556101408201516009820155610160820151600a82015561018090910151600b9091015560008381526021602052604080822086905560065481516340c10f1960e01b81526001600160a01b038e8116600483015260248201889052925192909116926340c10f199260448084019382900301818387803b158015614af757600080fd5b505af1158015614b0b573d6000803e3d6000fd5b5050506001600160a01b0386166000908152601b60205260408120859055614b3891508a90600190614012565b836020600085815260200190815260200160002060010181905550816001600160a01b03166333a8383c868986888e876040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b0316815260200180602001868152602001858152602001848152602001838152602001828103825287818151815260200191508051906020019080838360005b83811015614be4578181015183820152602001614bcc565b50505050905090810190601f168015614c115780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b158015614c3557600080fd5b505af1158015614c49573d6000803e3d6000fd5b50505050614c6160018461400090919063ffffffff16565b601255614c6d856157ff565b509098975050505050505050565b614c83615c7e565b506040805180820190915281518152602082810190820152919050565b6060614cab82615919565b614cb457600080fd5b6000614cbf83615953565b9050606081604051908082528060200260200182016040528015614cfd57816020015b614cea615c7e565b815260200190600190039081614ce25790505b5090506000614d0f85602001516159af565b60208601510190506000805b84811015614d6657614d2c83615a12565b9150604051806040016040528083815260200184815250848281518110614d4f57fe5b602090810291909101015291810191600101614d1b565b509195945050505050565b805160009015801590614d8657508151602110155b614d8f57600080fd5b6000614d9e83602001516159af565b83516020808601518301805193945091849003929190831015614dc857826020036101000a820491505b50949350505050565b8051600090600114614de257600080fd5b6020820151805160001a908115614dfa576001614dfd565b60005b949350505050565b6000828152601a60205260408120600601546001600160a01b03168015614e7a57806001600160a01b031663f83d08ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015614e6157600080fd5b505af1158015614e75573d6000803e3d6000fd5b505050505b600954614e8d818563ffffffff61400016565b6000868152601a602052604080822060048082019490945560068101805460ff60a01b1916600160a11b1790556005805491015482516381dc101b60e01b81529485018a9052602485018690526001600160a01b03908116604486015291519116926381dc101b92606480830193919282900301818387803b158015614f1257600080fd5b505af1158015614f26573d6000803e3d6000fd5b5050506000868152601a60205260409020600a81015490546140fc92509063ffffffff61400016565b600080825160208401856127105a03f43d604051816000823e828015614f73578282f35b8282fd5b602254614f8a908263ffffffff61422716565b6022556005546040805163122b648160e01b81526001600160a01b038581166004830152602482018590529151919092169163122b648191604480830192600092919082900301818387803b158015614fe257600080fd5b505af11580156123f2573d6000803e3d6000fd5b6003546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561504c57600080fd5b505af1158015615060573d6000803e3d6000fd5b505050506040513d602081101561507657600080fd5b5051611cb4576040805162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b6000818152601a60205260409020600601546001600160a01b03163314612e43576040805162461bcd60e51b815260206004820152601860248201527f496e76616c696420636f6e747261637420616464726573730000000000000000604482015290519081900360640190fd5b6000828152601a6020526040812060019081015461514c9163ffffffff61422716565b601454909150615162908263ffffffff61400016565b6014556000838152601a60205260409020600181810155602454600b9091015561518c8282614ff6565b60055460145460408051635b42d93560e11b815260048101879052602481018590526044810192909252516001600160a01b039092169163b685b26a9160648082019260009290919082900301818387803b1580156135f057600080fd5b6000828152601a60205260409020600a015461520c908263ffffffff61400016565b6000928352601a6020526040909220600a019190915550565b6000805460ff19169055565b600080821161523f57600080fd5b600082848161524a57fe5b04949350505050565b6001600160a01b03811661526657600080fd5b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b60008151604014615304576040805162461bcd60e51b81526020600482015260076024820152663737ba10383ab160c91b604482015290519081900360640190fd5b815160208301206001600160a01b0381161580159061533957506001600160a01b0381166000908152601b6020526040902054155b611a74576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b604482015290519081900360640190fd5b6153848261543d565b611cb4816157ff565b6000805460ff19166001179055565b6000838152601a60205260409020600b01548281101561541b576000848152601a602052604090208054600a9091015480156154035760006153e4838363ffffffff61400016565b90506153fd8784846153f88b868c8b615aab565b615acf565b50615418565b6154188661541388858988615aab565b615b75565b50505b80821115611d74576000848152601a60205260409020600b0182905550505050565b6026805490600090600019830183811061545357fe5b600091825260209091200154602680546001600160a01b03909216925090600019840190811061547f57fe5b600091825260209091200180546001600160a01b031916905560001982015b801561553657836001600160a01b0316826001600160a01b031614156154c357615536565b602660018203815481106154d357fe5b9060005260206000200160009054906101000a90046001600160a01b0316826026600184038154811061550257fe5b600091825260209091200180546001600160a01b0319166001600160a01b039290921691909117905591506000190161549e565b506000198201611d74602682615c98565b60008261555657506000611a74565b8282028284828161556357fe5b041461215c57600080fd5b600e54600b54600091908261558e83888161558557fe5b04602954615bb3565b90506000811180156155a257506027548114155b156155e357602754156155dd5760006064602a548402816155bf57fe5b0490508160275411156155d557918201916155db565b80830392505b505b60278190555b60008388111561567c5760285461562b61561b60646145c161560e6002600019890189020486615547565b889063ffffffff61554716565b611b29868663ffffffff61554716565b915061564d615640848763ffffffff61554716565b8a9063ffffffff61422716565b985061567861566b60646145c1846146b5898963ffffffff61554716565b859063ffffffff61422716565b9350505b6156a0615693856145c18b8763ffffffff61554716565b829063ffffffff61400016565b90506156b6866145c1838a63ffffffff61554716565b98975050505050505050565b60245460005b83811015613168576156ee8582815181106156df57fe5b6020026020010151838561539c565b6001016156c8565b600954600061570c82600163ffffffff61400016565b9050615716615c7e565b506000818152601e6020908152604080832081518083019092528054808352600190910154928201839052909261574d9290614012565b506000918252601e6020526040822082815560010191909155600955565b6000808261577e575060009050806157f6565b6000615794846145c1888863ffffffff61554716565b6000888152601a602052604090206007015490915080156157db576157d86157cb60646145c1846146b58b8863ffffffff61422716565b839063ffffffff61400016565b91505b60006157ed878463ffffffff61422716565b92945091925050505b94509492505050565b6026805460018101825560008290527f744a2cf8fd7008e3d53b67916e73460df9fa5214e3ef23dd4259ca09493a35940180546001600160a01b0319166001600160a01b0384161790555460001901805b80156158d15760006026600183038154811061586857fe5b6000918252602090912001546001600160a01b039081169150841681101561589057506158d1565b806026838154811061589e57fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790555060001901615850565b8181146129b55782602682815481106158e657fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b805160009061592a57506000611708565b6020820151805160001a9060c082101561594957600092505050611708565b5060019392505050565b805160009061596457506000611708565b6000809050600061597884602001516159af565b602085015185519181019250015b808210156159a65761599782615a12565b60019093019290910190615986565b50909392505050565b8051600090811a60808110156159c9576000915050611708565b60b88110806159e4575060c081108015906159e4575060f881105b156159f3576001915050611708565b60c0811015615a075760b519019050611708565b60f519019050611708565b80516000908190811a6080811015615a2d5760019150615aa4565b60b8811015615a4257607e1981019150615aa4565b60c0811015615a6f5760b78103600185019450806020036101000a85510460018201810193505050615aa4565b60f8811015615a845760be1981019150615aa4565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60008183036144b96a084595161401484a0000006145c1838863ffffffff61554716565b6000615ae1838563ffffffff61400016565b9050600080615af28787868661576b565b90925090508015615b32576000878152601a6020526040902060090154615b1f908263ffffffff61400016565b6000888152601a60205260409020600901555b8115613604576000878152601a6020526040902060010154615b5a908363ffffffff61400016565b6000888152601a602052604090206001015550505050505050565b8015611cb4576000828152601a6020526040902060010154615b9d908263ffffffff61400016565b6000838152601a60205260409020600101555050565b6000818310615bc2578161215c565b5090919050565b828054828255906000526020600020908101928215615c1e579160200282015b82811115615c1e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615be9565b50615c2a929150615cbc565b5090565b6040518060a0016040528060008152602001600081526020016060815260200160608152602001600081525090565b60405180606001604052806000815260200160608152602001600081525090565b604051806040016040528060008152602001600081525090565b8154818355818111156129b5576000838152602090206129b5918101908301615ce0565b61262d91905b80821115615c2a5780546001600160a01b0319168155600101615cc2565b61262d91905b80821115615c2a5760008155600101615ce656fe4f6e6c7920676f7665726e616e636520636f6e747261637420697320617574686f72697a6564a265627a7a72315820431c6a8057326866c4c2118b555375b4c31f1897330945422ed25bde58989ddc64736f6c63430005110032
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106106235760003560e01c80637d66975211610336578063b1d23f02116101c3578063e6692f491161010f578063f5e95acb116100ad578063f8a3176c11610087578063f8a3176c14611522578063fb1ef52c1461152a578063fba58f3414611553578063fc0c546a1461155b57610623565b8063f5e95acb14611493578063f771fc87146114fd578063f83d08ba1461151a57610623565b8063f24ccbfe116100e9578063f24ccbfe1461139b578063f28699fa146113a3578063f2fde38b146113c2578063f41a9642146113e857610623565b8063e6692f491461133b578063e8afa8e814611358578063eceec1d31461137e57610623565b8063cf3090121161017c578063d86d53e711610156578063d86d53e7146112eb578063dcd962b214611308578063e568959a1461132b578063e59ee0c61461133357610623565b8063cf309012146112a7578063d6de07d0146112af578063d7f5549d146112ce57610623565b8063b1d23f02146111e4578063b65de35e14611207578063bc8756a914611224578063c710e92214611256578063cbf383d514611282578063cd6b83881461129f57610623565b8063987ab9db11610282578063a440ab1e1161023b578063a69df4b511610215578063a69df4b5146111a0578063a7ab6961146111a8578063a8dc889b146111b0578063b184be81146111b857610623565b8063a440ab1e146110f8578063a476907114611115578063a68548771461111d57610623565b8063987ab9db1461106257806399d18f6f1461106a5780639a8a62431461108d5780639b33f434146110955780639ddbbf85146110b25780639ff11500146110d557610623565b8063883b455f116102ef578063900cf0cf116102c9578063900cf0cf14611018578063914601491461102057806391f1a3a51461103d5780639342c8f41461104557610623565b8063883b455f146110005780638da5cb5b146110085780638f32d59b1461101057610623565b80637d66975214610f8b5780637ed4b27c14610f935780637f4b432314610fb05780637f952d9514610fcd578063817b1cd214610fd5578063858a7c0314610fdd57610623565b8063451b5985116104b45780635e47655f116104005780637060054d116103b957806377939d101161039357806377939d1014610f4d57806378f84a4414610f555780637b10399914610f7b5780637c7eaf1a14610f8357610623565b80637060054d14610f35578063715018a614610f3d5780637667180814610f4557610623565b80635e47655f14610d7357806360c8d12214610de15780636352211e14610e0a5780636365679814610e2757806368cb812a14610e535780636901b25314610f0357610623565b806352b8115d1161046d5780635508d8e1116104475780635508d8e114610d3e57806356342d8c14610d465780635aa6e67514610d635780635ab1bd5314610d6b57610623565b806352b8115d14610bd75780635325e14414610c6f57806354b8c60114610d3657610623565b8063451b598514610a9657806348ab8b2a14610a9e5780634b341aed14610ada5780634e3c83f114610b005780634fd101d714610b085780634fdd20f114610b1057610623565b806325316411116105735780632fa9d18b1161052c57806335aa2e441161050657806335aa2e44146109925780633862da0b14610a4b57806339610f7814610a7157806341b3d18514610a8e57610623565b80632fa9d18b146108f357806331c2273b14610982578063342745861461098a57610623565b8063253164111461079b57806325726df2146107a35780632649263a146107d957806328cc4e411461080a5780632cf44a43146108355780632e17de78146108d657610623565b8063174e6832116105e05780631ae4818f116105ba5780631ae4818f146107175780631dd6b9b11461073b5780631e9b12ef146107585780632079fb9a1461077e57610623565b8063174e6832146106cc578063178c2c83146106f257806317c2b9101461070f57610623565b806306cfb10414610628578063078a13b1146106475780630cccfc58146106855780630e15561a1461069f5780630ebb172a146106a757806316827b1b146106af575b600080fd5b6106456004803603602081101561063e57600080fd5b5035611563565b005b6106456004803603608081101561065d57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060013516611570565b61068d6115e8565b60408051918252519081900360200190f35b61068d6115ee565b61068d6115f4565b610645600480360360208110156106c557600080fd5b50356115fa565b61068d600480360360208110156106e257600080fd5b50356001600160a01b0316611683565b6106456004803603602081101561070857600080fd5b503561170d565b61068d61199a565b61071f6119a0565b604080516001600160a01b039092168252519081900360200190f35b6106456004803603602081101561075157600080fd5b50356119af565b6106456004803603602081101561076e57600080fd5b50356001600160a01b03166119bc565b61071f6004803603602081101561079457600080fd5b50356119f9565b61068d611a20565b6107c0600480360360208110156107b957600080fd5b5035611a26565b6040805192835260208301919091528051918290030190f35b6107f6600480360360208110156107ef57600080fd5b5035611a3f565b604080519115158252519081900360200190f35b6106456004803603606081101561082057600080fd5b50803590602081013590604001351515611a7a565b6106456004803603602081101561084b57600080fd5b810190602081018135600160201b81111561086557600080fd5b82018360208201111561087757600080fd5b803590602001918460208302840111600160201b8311171561089857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611c90945050505050565b610645600480360360208110156108ec57600080fd5b5035611cb8565b61068d600480360360a081101561090957600080fd5b8135916020810135916040820135916001600160a01b036060820135169181019060a081016080820135600160201b81111561094457600080fd5b82018360208201111561095657600080fd5b803590602001918460608302840111600160201b8311171561097757600080fd5b509092509050611d7a565b61071f61208b565b61068d61209a565b6109af600480360360208110156109a857600080fd5b50356120a0565b604051808e81526020018d81526020018c81526020018b81526020018a8152602001896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b03168152602001876003811115610a0d57fe5b60ff1681526020018681526020018581526020018481526020018381526020018281526020019d505050505050505050505050505060405180910390f35b61068d60048036036020811015610a6157600080fd5b50356001600160a01b0316612111565b61068d60048036036020811015610a8757600080fd5b5035612123565b61068d612163565b61068d612169565b61064560048036036080811015610ab457600080fd5b508035906001600160a01b0360208201358116916040810135909116906060013561216f565b61068d60048036036020811015610af057600080fd5b50356001600160a01b03166121f6565b61068d61232d565b61068d612333565b610645600480360360a0811015610b2657600080fd5b6001600160a01b0382351691602081013591604082013591606081013515159181019060a081016080820135600160201b811115610b6357600080fd5b820183602082011115610b7557600080fd5b803590602001918460018302840111600160201b83111715610b9657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612339945050505050565b610645600480360360c0811015610bed57600080fd5b6001600160a01b038235169160208101359160408201359160608101359160808201351515919081019060c0810160a0820135600160201b811115610c3157600080fd5b820183602082011115610c4357600080fd5b803590602001918460018302840111600160201b83111715610c6457600080fd5b5090925090506123fa565b610c8c60048036036020811015610c8557600080fd5b5035612519565b60405180868152602001858152602001846001600160a01b03166001600160a01b031681526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610cf7578181015183820152602001610cdf565b50505050905090810190601f168015610d245780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b6107f66125df565b61068d6125e8565b61071f60048036036020811015610d5c57600080fd5b50356125ee565b61071f61260c565b61071f612620565b61068d60048036036020811015610d8957600080fd5b810190602081018135600160201b811115610da357600080fd5b820183602082011115610db557600080fd5b803590602001918460018302840111600160201b83111715610dd657600080fd5b509092509050612630565b61064560048036036060811015610df757600080fd5b5080359060208101359060400135612951565b61071f60048036036020811015610e2057600080fd5b50356129ba565b61064560048036036040811015610e3d57600080fd5b506001600160a01b038135169060200135612a06565b61064560048036036060811015610e6957600080fd5b813591602081013591810190606081016040820135600160201b811115610e8f57600080fd5b820183602082011115610ea157600080fd5b803590602001918460018302840111600160201b83111715610ec257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612a1b945050505050565b6107f660048036036060811015610f1957600080fd5b50803590602081013590604001356001600160a01b0316612bce565b61068d612c6b565b610645612c71565b61068d612ccc565b61068d612cd2565b61068d60048036036020811015610f6b57600080fd5b50356001600160a01b0316612cd8565b61071f612cea565b61068d612cf9565b61068d612cff565b61068d60048036036020811015610fa957600080fd5b5035612d05565b61068d60048036036020811015610fc657600080fd5b5035612d5c565b61068d612d71565b61068d612d77565b61064560048036036040811015610ff357600080fd5b5080359060200135612d7d565b61071f612dc3565b61071f612dd7565b6107f6612de6565b61068d612e29565b6106456004803603602081101561103657600080fd5b5035612e2f565b61068d612e46565b6106456004803603602081101561105b57600080fd5b5035612e4c565b61071f612e69565b6106456004803603604081101561108057600080fd5b5080359060200135612e78565b61068d612ede565b610645600480360360208110156110ab57600080fd5b5035612ee4565b610645600480360360408110156110c857600080fd5b5080359060200135612fa0565b610645600480360360408110156110eb57600080fd5b5080359060200135613006565b6106456004803603602081101561110e57600080fd5b503561309a565b61068d6130b1565b6106456004803603608081101561113357600080fd5b813591602081013591604082013515159190810190608081016060820135600160201b81111561116257600080fd5b82018360208201111561117457600080fd5b803590602001918460018302840111600160201b8311171561119557600080fd5b5090925090506130b7565b61064561316f565b61068d613181565b61068d613187565b610645600480360360408110156111ce57600080fd5b506001600160a01b03813516906020013561318d565b610645600480360360408110156111fa57600080fd5b508035906020013561319f565b61068d6004803603602081101561121d57600080fd5b50356131b2565b6107f66004803603606081101561123a57600080fd5b50803590602081013590604001356001600160a01b0316613200565b6106456004803603604081101561126c57600080fd5b50803590602001356001600160a01b0316613368565b6106456004803603602081101561129857600080fd5b5035613423565b61068d6134ac565b6107f66134b2565b610645600480360360208110156112c557600080fd5b503515156134bb565b61068d600480360360208110156112e457600080fd5b503561360d565b6106456004803603602081101561130157600080fd5b503561361f565b6106456004803603604081101561131e57600080fd5b5080359060200135613805565b61068d61386d565b6107c0613873565b6106456004803603602081101561135157600080fd5b503561387c565b6106456004803603602081101561136e57600080fd5b50356001600160a01b0316613938565b61068d6004803603602081101561139457600080fd5b50356139b8565b61071f6139ca565b610645600480360360208110156113b957600080fd5b503515156139d9565b610645600480360360208110156113d857600080fd5b50356001600160a01b03166139f4565b610645600480360360408110156113fe57600080fd5b81359190810190604081016020820135600160201b81111561141f57600080fd5b82018360208201111561143157600080fd5b803590602001918460018302840111600160201b8311171561145257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550613a0e945050505050565b61064560048036036101208110156114aa57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c082013581169160e08101358216916101009091013516613bfc565b6106456004803603602081101561151357600080fd5b5035613d9f565b610645613dba565b61071f613dca565b6106456004803603606081101561154057600080fd5b5080359060208101359060400135613dd9565b61068d613ef4565b61071f613efa565b61156b613f09565b600f55565b611578613f09565b61158181613f57565b61158a57600080fd5b60238054610100600160a81b0319169055602580546001600160a01b03199081166001600160a01b03938416179091556006805482169583169590951790945560058054851693821693909317909255600780549093169116179055565b60155481565b60135481565b60085481565b611602613f09565b8061160c57600080fd5b60055460105460408051630f1980a560e41b8152600481018590526024810192909252516001600160a01b039092169163f1980a509160448082019260009290919082900301818387803b15801561166357600080fd5b505af1158015611677573d6000803e3d6000fd5b50505060109190915550565b60065460408051632f745c5960e01b81526001600160a01b038481166004830152600060248301819052925192931691632f745c5991604480820192602092909190829003018186803b1580156116d957600080fd5b505afa1580156116ed573d6000803e3d6000fd5b505050506040513d602081101561170357600080fd5b505190505b919050565b8061171781613f76565b60026000838152601a6020526040902060060154600160a01b900460ff16600381111561174057fe5b1461177f576040805162461bcd60e51b815260206004820152600a602482015269139bdd081a985a5b195960b21b604482015290519081900360640190fd5b6000828152601a6020526040902060030154156117d7576040805162461bcd60e51b8152602060048201526011602482015270416c726561647920756e7374616b696e6760781b604482015290519081900360640190fd5b6009546000838152601a6020526040902060040154811015611839576040805162461bcd60e51b8152602060048201526016602482015275125b98dbdb5c1b195d19481a985a5b081c195c9a5bd960521b604482015290519081900360640190fd5b6000838152601a6020526040902054600c5481101561185757600080fd5b6000848152601a60205260409020600601546001600160a01b031680156118cc57806001600160a01b031663a69df4b56040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156118b357600080fd5b505af11580156118c7573d6000803e3d6000fd5b505050505b6000858152601a60205260409020600a01546118fc906118f390849063ffffffff61400016565b60016000614012565b6000858152601a602052604080822060068101805460ff60a01b1916600160a01b1790556005908101549054825163f92ec5af60e01b8152600481018a90526001600160a01b039283166024820181905293519394929091169263f92ec5af9260448084019391929182900301818387803b15801561197a57600080fd5b505af115801561198e573d6000803e3d6000fd5b50505050505050505050565b60175481565b6007546001600160a01b031681565b6119b7613f09565b600955565b6119c4613f09565b6001600160a01b0381166119d757600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60268181548110611a0657fe5b6000918252602090912001546001600160a01b0316905081565b600e5481565b601e602052600090815260409020805460019091015482565b6000818152601a6020526040812060068101548154600390920154600954611a7493600160a01b90930460ff169291906140cd565b92915050565b611a82614105565b82611a8c81613f76565b6000848152601a602052604090206003015415611adf576040805162461bcd60e51b815260206004820152600c60248201526b4e6f2072657374616b696e6760a01b604482015290519081900360640190fd5b8215611af057611af0333085614146565b611af984614218565b8115611b4c576000848152601a60205260409020600190810154611b359190611b2990869063ffffffff61400016565b9063ffffffff61422716565b6000858152601a6020526040902060019081015592505b601154600090611b62908563ffffffff61400016565b60118190556000868152601a6020526040902054909150611b89908563ffffffff61400016565b6000868152601a6020526040812091909155611ba790859080614012565b6005546040805163532e19a960e01b81526004810188905290516001600160a01b039092169163532e19a99160248082019260009290919082900301818387803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b50506005546000888152601a6020526040808220548151631585a9f360e21b8152600481018c905260248101919091526044810187905290516001600160a01b039093169450635616a7cc93506064808201939182900301818387803b158015611c7157600080fd5b505af1158015611c85573d6000803e3d6000fd5b505050505050505050565b611c98612de6565b611ca157600080fd5b8051611cb4906026906020840190615bc9565b5050565b80611cc281613f76565b600082815260208052604090205415611cda57600080fd5b6000828152601a602052604090206006810154600290910154600160a01b90910460ff169015801590611d1c57506000838152601a6020526040902060030154155b8015611d4857506001816003811115611d3157fe5b1480611d4857506002816003811115611d4657fe5b145b611d5157600080fd5b600954600090611d6890600163ffffffff61400016565b9050611d74848261423c565b50505050565b6002546000906001600160a01b03163314611d9457600080fd5b600954601d546000908190611da7615c2e565b6026546040805191840180835260208082028401019091528015611dd5578160200160208202803883390190505b5060408083019190915260268054825160208083028201810190945281815292830182828015611e2e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611e10575b50505050506060820152600060208201526026546080820152611e4f615c5d565b6026546040805191850180835260208082028401019091528015611e7d578160200160208202803883390190505b50602082015260005b8881101561204c576000611ed48e8c8c85818110611ea057fe5b90506060020160038060200260405190810160405280929190826003602002808284376000920191909152506143c0915050565b9050856001600160a01b0316816001600160a01b03161415611ef65750612044565b856001600160a01b0316816001600160a01b03161015611f16575061204c565b6001600160a01b0381166000908152601b6020908152604080832054808452601a909252909120805460068201546003909201548087529091600160a01b900460ff1690611f6890829084908e6140cd565b15611ff3576000838152601a60205260409020600a01549398508893611fa7908390611f9b908d9063ffffffff61400016565b9063ffffffff61400016565b8651909a5015611fe157828660200151876040015181518110611fc657fe5b60209081029190910101526040860180516001019052611fee565b611feb87856144c3565b96505b61203f565b600281600381111561200157fe5b141561203f5782876040015188600001518151811061201c57fe5b602090810291909101810191909152875160019081018952908801805190910190525b505050505b600101611e86565b506120588260006144c3565b915061207a8d8b878e86604001518760000151876020015188604001516145a0565b9d9c50505050505050505050505050565b6006546001600160a01b031681565b60165481565b601a60205260009081526040902080546001820154600283015460038401546004850154600586015460068701546007880154600889015460098a0154600a8b0154600b909b0154999a98999798969795966001600160a01b039586169695851695600160a01b90950460ff16948d565b601b6020526000908152604090205481565b60008061212f83614708565b6000858152601a602052604090206009015490925061215c9150600190611b29908463ffffffff61400016565b9392505050565b600c5481565b60295481565b612177613f09565b6000848152601a60205260409020600601546001600160a01b03168061219c57600080fd5b6040805163abf59fc960e01b81526001600160a01b03868116600483015285811660248301526044820185905291519183169163abf59fc99160648082019260009290919082900301818387803b158015611c7157600080fd5b60006001600160a01b03821615806122845750600654604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b15801561225657600080fd5b505afa15801561226a573d6000803e3d6000fd5b505050506040513d602081101561228057600080fd5b5051155b1561229157506000611708565b60065460408051632f745c5960e01b81526001600160a01b0385811660048301526000602483018190529251601a949190911691632f745c59916044808301926020929190829003018186803b1580156122ea57600080fd5b505afa1580156122fe573d6000803e3d6000fd5b505050506040513d602081101561231457600080fd5b5051815260208101919091526040016000205492915050565b600f5481565b60105481565b612341614105565b60105461234c612d71565b1061238e576040805162461bcd60e51b815260206004820152600d60248201526c6e6f206d6f726520736c6f747360981b604482015290519081900360640190fd5b600c548410156123da576040805162461bcd60e51b81526020600482015260126024820152711b9bdd08195b9bdd59da0819195c1bdcda5d60721b604482015290519081900360640190fd5b6123e685338587614784565b6123f28585848461486e565b505050505050565b33301461243c576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6124498788886000614784565b6124558560095461423c565b600061249988868686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061486e92505050565b6005546040805163e12ab1af60e01b815260048101849052602481018a90526044810189905290519293506001600160a01b039091169163e12ab1af9160648082019260009290919082900301818387803b1580156124f757600080fd5b505af115801561250b573d6000803e3d6000fd5b505050505050505050505050565b60208080526000918252604091829020805460018083015460028085015460038601805489516101009682161596909602600019011692909204601f8101889004880285018801909852878452939691956001600160a01b03851695600160a01b90950460ff16949392908301828280156125d55780601f106125aa576101008083540402835291602001916125d5565b820191906000526020600020905b8154815290600101906020018083116125b857829003601f168201915b5050505050905085565b60195460ff1681565b60125481565b6000908152601a60205260409020600601546001600160a01b031690565b60005461010090046001600160a01b031681565b6004546001600160a01b03165b90565b6004805460408051631ab0168360e31b8152905160009333936001600160a01b03169263d580b4189281830192602092829003018186803b15801561267457600080fd5b505afa158015612688573d6000803e3d6000fd5b505050506040513d602081101561269e57600080fd5b50516001600160a01b0316146126ef576040805162461bcd60e51b81526020600482015260116024820152702737ba1039b630b9b41036b0b730b3b2b960791b604482015290519081900360640190fd5b606061273861273385858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250614c7b92505050565b614ca0565b90506000806000805b845181101561292557606061276886838151811061275b57fe5b6020026020010151614ca0565b905060006127898260008151811061277c57fe5b6020026020010151614d71565b905061279481614218565b60006127a68360018151811061277c57fe5b90506127b8858263ffffffff61400016565b6000838152601a60205260409020600601549095506001600160a01b03168015612886576000838152601a602090815260408083208054600a9091015482516306cbb60560e41b8152600481019290925260248201526044810186905290516001600160a01b03851692636cbb6050926064808201939182900301818787803b15801561284457600080fd5b505af1158015612858573d6000803e3d6000fd5b505050506040513d602081101561286e57600080fd5b50519050612882838263ffffffff61422716565b9250505b6000838152601a60205260408120546128a5908463ffffffff61422716565b6000858152601a602052604090208190559050806128ce576128c98460095461423c565b612914565b6128eb856002815181106128de57fe5b6020026020010151614dd1565b156129145761290b6128fe856001614e05565b899063ffffffff61400016565b60019099019897505b505060019093019250612741915050565b612946612938838563ffffffff61400016565b600003856000036000614012565b509695505050505050565b612959613f09565b60255460408051602481018690526044810185905260648082018590528251808303909101815260849091019091526020810180516001600160e01b0316633064689160e11b1790526129b5916001600160a01b031690614f4f565b505050565b600654604080516331a9108f60e11b81526004810184905290516000926001600160a01b031691636352211e916024808301926020929190829003018186803b1580156116d957600080fd5b612a0e614105565b611cb48233836000614784565b60408051336020808301919091528183018690528251808303840181526060830193849052805190820120601754631b23d15760e21b909452606483018181526084840187905260a48401859052608060c48501908152865160e4860152865173540bde6642a8cb547a6887934044e465914112d096636c8f455c9694958a9591948a9490939092610104019185019080838360005b83811015612ac9578181015183820152602001612ab1565b50505050905090810190601f168015612af65780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038186803b158015612b1657600080fd5b505af4158015612b2a573d6000803e3d6000fd5b505050506040513d6020811015612b4057600080fd5b5051612b85576040805162461bcd60e51b815260206004820152600f60248201526e2bb937b7339030b1b190383937b7b360891b604482015290519081900360640190fd5b336000908152601f6020526040812054612ba690859063ffffffff61422716565b9050612bb23382614f77565b336000818152601f60205260409020859055611d749082614ff6565b600083612bda816150bb565b600354604080516323b872dd60e01b81526001600160a01b03868116600483015230602483015260448201889052915191909216916323b872dd9160648083019260209291908290030181600087803b158015612c3657600080fd5b505af1158015612c4a573d6000803e3d6000fd5b505050506040513d6020811015612c6057600080fd5b505195945050505050565b600a5481565b612c79612de6565b612c8257600080fd5b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b60095481565b60185481565b601f6020526000908152604090205481565b6004546001600160a01b031681565b602a5481565b600b5481565b600081612d11816150bb565b612d1a83614218565b6000838152601a6020526040812060090154612d3d90600163ffffffff61422716565b6000858152601a60205260409020600160099091015592505050919050565b6000908152601a60205260409020600a015490565b601d5490565b60115481565b81612d87816150bb565b6000838152601a60205260409020600a0154612da9908363ffffffff61422716565b6000938452601a6020526040909320600a01929092555050565b60235461010090046001600160a01b031681565b6001546001600160a01b031690565b604080517f6d617469632e6e6574776f726b2e70726f78792e6f776e6572000000000000008152905190819003601901902054336001600160a01b039091161490565b60095490565b612e37613f09565b612e438160095461423c565b50565b60275481565b80612e5681613f76565b612e5f82614218565b611cb48233615129565b6002546001600160a01b031681565b612e80614105565b602554604080516024810185905260448101849052306064808301919091528251808303909101815260849091019091526020810180516001600160e01b031663561ad5c960e11b179052611cb4916001600160a01b031690614f4f565b60225481565b612eec613f09565b6005546016546040805163a3b1d8cb60e01b8152600481018590526024810192909252516001600160a01b039092169163a3b1d8cb9160448082019260009290919082900301818387803b158015612f4357600080fd5b505af1158015612f57573d6000803e3d6000fd5b505050506064811115612f9b576040805162461bcd60e51b8152602060048201526007602482015266746f6f2062696760c81b604482015290519081900360640190fd5b601655565b612fa8612de6565b612fb157600080fd5b602554604080516024810185905260448082018590528251808303909101815260649091019091526020810180516001600160e01b0316639ddbbf8560e01b179052611cb4916001600160a01b031690614f4f565b81613010816150bb565b60008213156130695760195460ff16613069576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b61307582600080614012565b6000821261308c5761308783836151ea565b6129b5565b6129b5838360001902612d7d565b6130a2613f09565b806130ac57600080fd5b600e55565b601c5490565b6130bf614105565b6025546040516024810187815260448201879052851515606483015260806084830190815260a48301859052613168936001600160a01b03169263a685487760e01b928a928a928a928a928a9260c40184848082843760008184015260408051601f19601f9093018316909401848103909201845252506020810180516001600160e01b03199a909a166001600160e01b03909a169990991790985250614f4f95505050505050565b5050505050565b613177613f09565b61317f615225565b565b60085490565b60245481565b613195613f09565b611cb48282614ff6565b6131a7613f09565b600c91909155600d55565b6000818152601a602052604081206003015481906131d7576131d383614708565b5090505b6000838152601a6020526040902060019081015461215c9190611b29908463ffffffff61400016565b6000838152601a60205260408120600601546001600160a01b031633148061329f57506004805460408051631ab0168360e31b8152905133936001600160a01b039093169263d580b41892808201926020929091829003018186803b15801561326857600080fd5b505afa15801561327c573d6000803e3d6000fd5b505050506040513d602081101561329257600080fd5b50516001600160a01b0316145b6132de576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6003546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018790529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561333457600080fd5b505af1158015613348573d6000803e3d6000fd5b505050506040513d602081101561335e57600080fd5b5051949350505050565b613370613f09565b306001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156133b357600080fd5b505afa1580156133c7573d6000803e3d6000fd5b505050506040513d60208110156133dd57600080fd5b50516001600160a01b0316146133f257600080fd5b6000918252601a602052604090912060060180546001600160a01b0319166001600160a01b03909216919091179055565b61342b613f09565b8061343557600080fd5b600554600b5460408051632dbe9d3160e21b8152600481018590526024810192909252516001600160a01b039092169163b6fa74c49160448082019260009290919082900301818387803b15801561348c57600080fd5b505af11580156134a0573d6000803e3d6000fd5b505050600b9190915550565b60145481565b60005460ff1681565b336000908152601b6020908152604080832054808452601a9092529091206006810154815460039092015460095461350093600160a01b90930460ff169291906140cd565b613541576040805162461bcd60e51b815260206004820152600d60248201526c3737ba103b30b634b230ba37b960991b604482015290519081900360640190fd5b6000818152601a60205260409020600601546001600160a01b0316806135a7576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b604080516303dd464160e51b8152841515600482015290516001600160a01b03831691637ba8c82091602480830192600092919082900301818387803b1580156135f057600080fd5b505af1158015613604573d6000803e3d6000fd5b50505050505050565b60216020526000908152604090205481565b8061362981613f76565b6000828152601a6020526040902060030154801580159061365f575060095460085461365c90839063ffffffff61400016565b11155b8015613692575060036000848152601a6020526040902060060154600160a01b900460ff16600381111561368f57fe5b14155b61369b57600080fd5b6000838152601a60205260408120546011549091906136c0908363ffffffff61422716565b601181905590506136d18533615129565b60065460408051630852cd8d60e31b81526004810188905290516001600160a01b03909216916342966c689160248082019260009290919082900301818387803b15801561371e57600080fd5b505af1158015613732573d6000803e3d6000fd5b5050506000868152601a6020526040812081815560048101919091556005810180546001600160a01b03191690556000197f584f46c60af19681376031579adb04a2416e54ee5505351c2a8435e3766026ea55600601805460ff60a01b1916600360a01b179055506137a43383614ff6565b6005546040805163ae2e26b160e01b815233600482015260248101889052604481018590526064810184905290516001600160a01b039092169163ae2e26b19160848082019260009290919082900301818387803b158015611c7157600080fd5b8161380f81613f76565b61381883614218565b602554604080516024810186905260448082018690528251808303909101815260649091019091526020810180516001600160e01b0316636e6cb15960e11b1790526129b5916001600160a01b031690614f4f565b60285481565b601c54601d5482565b613884613f09565b6000811161389157600080fd5b600554600a5460408051635071805360e11b8152600481018590526024810192909252516001600160a01b039092169163a0e300a69160448082019260009290919082900301818387803b1580156138e857600080fd5b505af11580156138fc573d6000803e3d6000fd5b505050600a82905550600881905561391b81600463ffffffff61523116565b60158190556009546139329163ffffffff61400016565b60185550565b613940612de6565b61394957600080fd5b6001600160a01b03811661395c57600080fd5b6002546040516001600160a01b038084169216907f211c9015fc81c0dbd45bd99f0f29fc1c143bfd53442d5ffd722bbbef7a887fe990600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000908152601a602052604090205490565b6005546001600160a01b031681565b6139e1613f09565b6019805460ff1916911515919091179055565b6139fc612de6565b613a0557600080fd5b612e4381615253565b81613a1881613f76565b6000613a23836152c2565b600954600f546000878152602160205260409020549293509091613a4c9163ffffffff61400016565b811015613a8e576040805162461bcd60e51b815260206004820152600b60248201526a139bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6000858152601a602090815260408083206005908101549054915163b80fbce560e01b8152600481018a81526001600160a01b039283166024830181905288841660448401526080606484019081528b5160848501528b519197949095169563b80fbce5958d9589958c958f95909460a490920192918601918190849084905b83811015613b26578181015183820152602001613b0e565b50505050905090810190601f168015613b535780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015613b7557600080fd5b505af1158015613b89573d6000803e3d6000fd5b5050506001600160a01b038083166000908152601b6020908152604080832060001990559287168083528383208b90558a8352601a90915291902060050180546001600160a01b031916909117905550613be3818461537b565b5060009485526021602052604090942093909355505050565b60235460ff1615613c45576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6023805460ff19166001179055613c5b81613f57565b613ca5576040805162461bcd60e51b8152602060048201526016602482015275185d58dd1a5bdb881a5b5c1b081a5b98dbdc9c9958dd60521b604482015290519081900360640190fd5b602580546001600160a01b03199081166001600160a01b038481169190911790925560008054610100600160a81b031916610100878516021790556004805482168c84161790556002805482168b84161790556003805482168a841617905560068054821689841617905560058054821688841617905560078054909116918616919091179055613d3582615253565b5050612000600855505060016009819055610376600a90815569044664c7bf6451f00000600b55670de0b6b3a7640000600c819055600d55610400600e556064600f55600760105560128290556108006015556016556019805460ff191690911790555050505050565b613da7613f09565b600954613932908263ffffffff61400016565b613dc2613f09565b61317f61538d565b6025546001600160a01b031681565b60078211613e22576040805162461bcd60e51b815260206004820152601160248201527024b73b30b634b21036b4b3b930ba34b7b760791b604482015290519081900360640190fd5b6000838152601a6020526040808220600601548151636e7ce59160e01b81523360048201526024810185905291516001600160a01b0390911692636e7ce591926044808201939182900301818387803b158015613e7e57600080fd5b505af1158015613e92573d6000803e3d6000fd5b5050506000838152601a6020526040808220600601548151632830728d60e21b81523360048201526024810186905291516001600160a01b03909116935063a0c1ca349260448084019391929182900301818387803b1580156135f057600080fd5b600d5481565b6003546001600160a01b031681565b60005461010090046001600160a01b0316331461317f5760405162461bcd60e51b8152600401808060200182810382526026815260200180615cfb6026913960400191505060405180910390fd5b60006001600160a01b038216613f6f57506000611708565b503b151590565b600654604080516331a9108f60e11b815260048101849052905133926001600160a01b031691636352211e916024808301926020929190829003018186803b158015613fc157600080fd5b505afa158015613fd5573d6000803e3d6000fd5b505050506040513d6020811015613feb57600080fd5b50516001600160a01b031614612e4357600080fd5b60008282018381101561215c57600080fd5b806140ab57600083131561403b57601c54614033908463ffffffff61400016565b601c5561405f565b600083121561405f57601c5461405b90600085900363ffffffff61422716565b601c555b600082131561408357601d5461407b908363ffffffff61400016565b601d55613087565b600082121561308757601d546140a390600084900363ffffffff61422716565b601d556129b5565b6000818152601e60205260409020805484018155600101805483019055505050565b600080841180156140e557508215806140e557508183115b80156140fc575060018560038111156140fa57fe5b145b95945050505050565b60005460ff161561317f576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b600354604080516323b872dd60e01b81526001600160a01b038681166004830152858116602483015260448201859052915191909216916323b872dd9160648083019260209291908290030181600087803b1580156141a457600080fd5b505af11580156141b8573d6000803e3d6000fd5b505050506040513d60208110156141ce57600080fd5b50516129b5576040805162461bcd60e51b81526020600482015260146024820152731d1c985b9cd9995c88199c9bdb4819985a5b195960621b604482015290519081900360640190fd5b612e438160245460245461539c565b60008282111561423657600080fd5b50900390565b61424582614218565b6000828152601a60205260408120549061425e846129ba565b6000858152601a6020526040902060038101859055600a810154600690910154919250906001600160a01b031680156142e557806001600160a01b031663f83d08ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156142cc57600080fd5b505af11580156142e0573d6000803e3d6000fd5b505050505b6000868152601a6020526040902060050154614309906001600160a01b031661543d565b6143138684615129565b60006009548611156143255785614328565b60005b905061433c83860160000360001983614012565b60055460408051635e04d48360e01b81526001600160a01b038781166004830152602482018b9052604482018a90526064820189905291519190921691635e04d48391608480830192600092919082900301818387803b15801561439f57600080fd5b505af11580156143b3573d6000803e3d6000fd5b5050505050505050505050565b805160208201516040830151600092919060ff167f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156144085760009350505050611a74565b601b8160ff16101561441857601b015b8060ff16601b1415801561443057508060ff16601c14155b156144415760009350505050611a74565b60408051600080825260208083018085528a905260ff85168385015260608301879052608083018690529251909260019260a080820193601f1981019281900390910190855afa158015614499573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166144b957600080fd5b9695505050505050565b6144cb615c2e565b8260800151836020015110801561450f5750816001600160a01b031683606001518460200151815181106144fb57fe5b60200260200101516001600160a01b031614155b1561459057601b6000846060015185602001518151811061452c57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054836040015184600001518151811061456957fe5b602090810291909101810191909152835160019081018552908401805190910190526144cb565b5050602081018051600101905290565b601c546000906145cd6001611f9b60036145c185600263ffffffff61554716565b9063ffffffff61523116565b881015614617576040805162461bcd60e51b8152602060048201526013602482015272322f332b31206e6f6e2d6d616a6f726974792160681b604482015290519081900360640190fd5b60006146248b8a8461556e565b9050600061464260646145c16016548561554790919063ffffffff16565b6001600160a01b038c166000908152601b6020908152604080832054808452601a90925290912060018101549293509091614683908463ffffffff61400016565b600182015560178b905560006146d06146c18e6145c16a084595161401484a0000006146b58a8a63ffffffff61422716565b9063ffffffff61554716565b6024549063ffffffff61400016565b90506146dd8b8b836156c2565b60248190556146ed8989836156c2565b6146f56156f6565b50929d9c50505050505050505050505050565b6000818152601a602052604081208054600a90910154829190829061473490839063ffffffff61400016565b6000868152601a60205260409020600b0154602454919250900361477886846147726a084595161401484a0000006145c1868863ffffffff61554716565b8561576b565b94509450505050915091565b600d548210156147cb576040805162461bcd60e51b815260206004820152600d60248201526c199959481d1bdbc81cdb585b1b609a1b604482015290519081900360640190fd5b6147e583306147e0858563ffffffff61400016565b614146565b6022546147f8908363ffffffff61400016565b6022556005546040805163a449d79560e01b81526001600160a01b038781166004830152602482018690529151919092169163a449d79591604480830192600092919082900301818387803b15801561485057600080fd5b505af1158015614864573d6000803e3d6000fd5b5050505050505050565b60008061487a836152c2565b600954601254600554601154939450919290916001600160a01b0316906000906148aa908a63ffffffff61400016565b905080601181905550604051806101a001604052808a8152602001600181526020018581526020016000815260200160008152602001866001600160a01b03168152602001896148fb576000614987565b600754600480546040805163d4ad267360e01b81529283018990526001600160a01b03888116602485015291821660448401525192169163d4ad2673916064808201926020929091908290030181600087803b15801561495a57600080fd5b505af115801561496e573d6000803e3d6000fd5b505050506040513d602081101561498457600080fd5b50515b6001600160a01b031681526020016001815260006020808301829052604080840183905260016060808601829052608080870186905260245460a0978801528a8652601a855294839020875181559387015191840191909155908501516002830155840151600380830191909155918401516004820155918301516005830180546001600160a01b039283166001600160a01b03199182161790915560c08501516006850180549190931691161780825560e08501519260ff60a01b1990911690600160a01b908490811115614a5957fe5b0217905550610100820151600782015561012082015160088201556101408201516009820155610160820151600a82015561018090910151600b9091015560008381526021602052604080822086905560065481516340c10f1960e01b81526001600160a01b038e8116600483015260248201889052925192909116926340c10f199260448084019382900301818387803b158015614af757600080fd5b505af1158015614b0b573d6000803e3d6000fd5b5050506001600160a01b0386166000908152601b60205260408120859055614b3891508a90600190614012565b836020600085815260200190815260200160002060010181905550816001600160a01b03166333a8383c868986888e876040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b0316815260200180602001868152602001858152602001848152602001838152602001828103825287818151815260200191508051906020019080838360005b83811015614be4578181015183820152602001614bcc565b50505050905090810190601f168015614c115780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b158015614c3557600080fd5b505af1158015614c49573d6000803e3d6000fd5b50505050614c6160018461400090919063ffffffff16565b601255614c6d856157ff565b509098975050505050505050565b614c83615c7e565b506040805180820190915281518152602082810190820152919050565b6060614cab82615919565b614cb457600080fd5b6000614cbf83615953565b9050606081604051908082528060200260200182016040528015614cfd57816020015b614cea615c7e565b815260200190600190039081614ce25790505b5090506000614d0f85602001516159af565b60208601510190506000805b84811015614d6657614d2c83615a12565b9150604051806040016040528083815260200184815250848281518110614d4f57fe5b602090810291909101015291810191600101614d1b565b509195945050505050565b805160009015801590614d8657508151602110155b614d8f57600080fd5b6000614d9e83602001516159af565b83516020808601518301805193945091849003929190831015614dc857826020036101000a820491505b50949350505050565b8051600090600114614de257600080fd5b6020820151805160001a908115614dfa576001614dfd565b60005b949350505050565b6000828152601a60205260408120600601546001600160a01b03168015614e7a57806001600160a01b031663f83d08ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015614e6157600080fd5b505af1158015614e75573d6000803e3d6000fd5b505050505b600954614e8d818563ffffffff61400016565b6000868152601a602052604080822060048082019490945560068101805460ff60a01b1916600160a11b1790556005805491015482516381dc101b60e01b81529485018a9052602485018690526001600160a01b03908116604486015291519116926381dc101b92606480830193919282900301818387803b158015614f1257600080fd5b505af1158015614f26573d6000803e3d6000fd5b5050506000868152601a60205260409020600a81015490546140fc92509063ffffffff61400016565b600080825160208401856127105a03f43d604051816000823e828015614f73578282f35b8282fd5b602254614f8a908263ffffffff61422716565b6022556005546040805163122b648160e01b81526001600160a01b038581166004830152602482018590529151919092169163122b648191604480830192600092919082900301818387803b158015614fe257600080fd5b505af11580156123f2573d6000803e3d6000fd5b6003546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561504c57600080fd5b505af1158015615060573d6000803e3d6000fd5b505050506040513d602081101561507657600080fd5b5051611cb4576040805162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b6000818152601a60205260409020600601546001600160a01b03163314612e43576040805162461bcd60e51b815260206004820152601860248201527f496e76616c696420636f6e747261637420616464726573730000000000000000604482015290519081900360640190fd5b6000828152601a6020526040812060019081015461514c9163ffffffff61422716565b601454909150615162908263ffffffff61400016565b6014556000838152601a60205260409020600181810155602454600b9091015561518c8282614ff6565b60055460145460408051635b42d93560e11b815260048101879052602481018590526044810192909252516001600160a01b039092169163b685b26a9160648082019260009290919082900301818387803b1580156135f057600080fd5b6000828152601a60205260409020600a015461520c908263ffffffff61400016565b6000928352601a6020526040909220600a019190915550565b6000805460ff19169055565b600080821161523f57600080fd5b600082848161524a57fe5b04949350505050565b6001600160a01b03811661526657600080fd5b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b60008151604014615304576040805162461bcd60e51b81526020600482015260076024820152663737ba10383ab160c91b604482015290519081900360640190fd5b815160208301206001600160a01b0381161580159061533957506001600160a01b0381166000908152601b6020526040902054155b611a74576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b604482015290519081900360640190fd5b6153848261543d565b611cb4816157ff565b6000805460ff19166001179055565b6000838152601a60205260409020600b01548281101561541b576000848152601a602052604090208054600a9091015480156154035760006153e4838363ffffffff61400016565b90506153fd8784846153f88b868c8b615aab565b615acf565b50615418565b6154188661541388858988615aab565b615b75565b50505b80821115611d74576000848152601a60205260409020600b0182905550505050565b6026805490600090600019830183811061545357fe5b600091825260209091200154602680546001600160a01b03909216925090600019840190811061547f57fe5b600091825260209091200180546001600160a01b031916905560001982015b801561553657836001600160a01b0316826001600160a01b031614156154c357615536565b602660018203815481106154d357fe5b9060005260206000200160009054906101000a90046001600160a01b0316826026600184038154811061550257fe5b600091825260209091200180546001600160a01b0319166001600160a01b039290921691909117905591506000190161549e565b506000198201611d74602682615c98565b60008261555657506000611a74565b8282028284828161556357fe5b041461215c57600080fd5b600e54600b54600091908261558e83888161558557fe5b04602954615bb3565b90506000811180156155a257506027548114155b156155e357602754156155dd5760006064602a548402816155bf57fe5b0490508160275411156155d557918201916155db565b80830392505b505b60278190555b60008388111561567c5760285461562b61561b60646145c161560e6002600019890189020486615547565b889063ffffffff61554716565b611b29868663ffffffff61554716565b915061564d615640848763ffffffff61554716565b8a9063ffffffff61422716565b985061567861566b60646145c1846146b5898963ffffffff61554716565b859063ffffffff61422716565b9350505b6156a0615693856145c18b8763ffffffff61554716565b829063ffffffff61400016565b90506156b6866145c1838a63ffffffff61554716565b98975050505050505050565b60245460005b83811015613168576156ee8582815181106156df57fe5b6020026020010151838561539c565b6001016156c8565b600954600061570c82600163ffffffff61400016565b9050615716615c7e565b506000818152601e6020908152604080832081518083019092528054808352600190910154928201839052909261574d9290614012565b506000918252601e6020526040822082815560010191909155600955565b6000808261577e575060009050806157f6565b6000615794846145c1888863ffffffff61554716565b6000888152601a602052604090206007015490915080156157db576157d86157cb60646145c1846146b58b8863ffffffff61422716565b839063ffffffff61400016565b91505b60006157ed878463ffffffff61422716565b92945091925050505b94509492505050565b6026805460018101825560008290527f744a2cf8fd7008e3d53b67916e73460df9fa5214e3ef23dd4259ca09493a35940180546001600160a01b0319166001600160a01b0384161790555460001901805b80156158d15760006026600183038154811061586857fe5b6000918252602090912001546001600160a01b039081169150841681101561589057506158d1565b806026838154811061589e57fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790555060001901615850565b8181146129b55782602682815481106158e657fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b805160009061592a57506000611708565b6020820151805160001a9060c082101561594957600092505050611708565b5060019392505050565b805160009061596457506000611708565b6000809050600061597884602001516159af565b602085015185519181019250015b808210156159a65761599782615a12565b60019093019290910190615986565b50909392505050565b8051600090811a60808110156159c9576000915050611708565b60b88110806159e4575060c081108015906159e4575060f881105b156159f3576001915050611708565b60c0811015615a075760b519019050611708565b60f519019050611708565b80516000908190811a6080811015615a2d5760019150615aa4565b60b8811015615a4257607e1981019150615aa4565b60c0811015615a6f5760b78103600185019450806020036101000a85510460018201810193505050615aa4565b60f8811015615a845760be1981019150615aa4565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60008183036144b96a084595161401484a0000006145c1838863ffffffff61554716565b6000615ae1838563ffffffff61400016565b9050600080615af28787868661576b565b90925090508015615b32576000878152601a6020526040902060090154615b1f908263ffffffff61400016565b6000888152601a60205260409020600901555b8115613604576000878152601a6020526040902060010154615b5a908363ffffffff61400016565b6000888152601a602052604090206001015550505050505050565b8015611cb4576000828152601a6020526040902060010154615b9d908263ffffffff61400016565b6000838152601a60205260409020600101555050565b6000818310615bc2578161215c565b5090919050565b828054828255906000526020600020908101928215615c1e579160200282015b82811115615c1e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615be9565b50615c2a929150615cbc565b5090565b6040518060a0016040528060008152602001600081526020016060815260200160608152602001600081525090565b60405180606001604052806000815260200160608152602001600081525090565b604051806040016040528060008152602001600081525090565b8154818355818111156129b5576000838152602090206129b5918101908301615ce0565b61262d91905b80821115615c2a5780546001600160a01b0319168155600101615cc2565b61262d91905b80821115615c2a5760008155600101615ce656fe4f6e6c7920676f7665726e616e636520636f6e747261637420697320617574686f72697a6564a265627a7a72315820431c6a8057326866c4c2118b555375b4c31f1897330945422ed25bde58989ddc64736f6c63430005110032
Deployed Bytecode Sourcemap
131680:45148:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;131680:45148:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;140666:116;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140666:116:0;;:::i;:::-;;141513:497;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;141513:497:0;;;;;;;;;;;;;;;;;;;;;;;;:::i;122381:28::-;;;:::i;:::-;;;;;;;;;;;;;;;;122303:27;;;:::i;121760:31::-;;;:::i;137739:237::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137739:237:0;;:::i;135306:134::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135306:134:0;-1:-1:-1;;;;;135306:134:0;;:::i;156833:1017::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;156833:1017:0;;:::i;122496:31::-;;;:::i;121703:50::-;;;:::i;:::-;;;;-1:-1:-1;;;;;121703:50:0;;;;;;;;;;;;;;137355:119;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137355:119:0;;:::i;137482:146::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137482:146:0;-1:-1:-1;;;;;137482:146:0;;:::i;123509:24::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;123509:24:0;;:::i;122106:38::-;;;:::i;122885:60::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;122885:60:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;136676:324;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;136676:324:0;;:::i;:::-;;;;;;;;;;;;;;;;;;147586:963;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;147586:963:0;;;;;;;;;;;;;;:::i;139345:104::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;139345:104:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;139345:104:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;139345: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;139345:104:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;139345:104:0;;-1:-1:-1;139345:104:0;;-1:-1:-1;;;;;139345:104:0:i;144699:538::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;144699:538:0;;:::i;151016:3184::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;151016:3184:0;;;;;;;;;;;;;-1:-1:-1;;;;;151016:3184:0;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;151016:3184:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;151016: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;151016:3184:0;;-1:-1:-1;151016:3184:0;-1:-1:-1;151016:3184:0;:::i;121667:29::-;;;:::i;122436:28::-;;;:::i;122686:47::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;122686:47:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;122686:47:0;-1:-1:-1;;;;;122686:47:0;;;;;;-1:-1:-1;;;;;122686:47:0;-1:-1:-1;;;;;122686:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;122740:52;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;122740:52:0;-1:-1:-1;;;;;122740:52:0;;:::i;135597:283::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135597:283:0;;:::i;122002:25::-;;;:::i;123781:37::-;;;:::i;140978:389::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;140978:389:0;;;-1:-1:-1;;;;;140978:389:0;;;;;;;;;;;;;;;;;;;:::i;142833:262::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;142833:262:0;-1:-1:-1;;;;;142833:262:0;;:::i;122151:32::-;;;:::i;122192:33::-;;;:::i;145910:481::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;145910:481:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;145910:481:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;145910: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;145910:481:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;145910:481:0;;-1:-1:-1;145910:481:0;;-1:-1:-1;;;;;145910:481:0:i;144064:627::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;144064:627:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;144064:627:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;144064: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;144064:627:0;;-1:-1:-1;144064:627:0;-1:-1:-1;144064:627:0;:::i;123047:51::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;123047:51:0;;:::i;:::-;;;;;;;;;;;;;;;-1:-1:-1;;;;;123047:51:0;-1:-1:-1;;;;;123047: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;123047:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;122648:29;;;:::i;122271:25::-;;;:::i;136522:146::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;136522:146:0;;:::i;25202:29::-;;;:::i;134686:87::-;;;:::i;155002:1823::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;155002:1823:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;155002:1823:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;155002: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;155002:1823:0;;-1:-1:-1;155002:1823:0;-1:-1:-1;155002:1823:0;:::i;138380:542::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;138380:542:0;;;;;;;;;;;;:::i;134841:118::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;134841:118:0;;:::i;142062:150::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;142062:150:0;;;;;;;;:::i;142220:605::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;142220:605:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;142220:605:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;142220: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;142220:605:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;142220:605:0;;-1:-1:-1;142220:605:0;;-1:-1:-1;;;;;142220:605:0:i;145655:247::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;145655:247:0;;;;;;;;;;;-1:-1:-1;;;;;145655:247:0;;:::i;121886:22::-;;;:::i;47149:140::-;;;:::i;121813:27::-;;;:::i;122607:34::-;;;:::i;122954:46::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;122954:46:0;-1:-1:-1;;;;;122954:46:0;;:::i;121605:23::-;;;:::i;123902:36::-;;;:::i;121938:32::-;;;:::i;154640:354::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;154640:354:0;;:::i;135448:141::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135448:141:0;;:::i;136271:117::-;;;:::i;122238:26::-;;;:::i;149936:226::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;149936:226:0;;;;;;;:::i;123407:24::-;;;:::i;46359:79::-;;;:::i;134374:255::-;;;:::i;134967:85::-;;;:::i;137226:121::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137226:121:0;;:::i;123592:32::-;;;:::i;148557:176::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;148557:176:0;;:::i;119632:24::-;;;:::i;143615:441::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;143615:441:0;;;;;;;:::i;123220:31::-;;;:::i;140388:270::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140388:270:0;;:::i;138967:370::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;138967:370:0;;;;;;;:::i;149201:520::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;149201:520:0;;;;;;;:::i;137984:162::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137984:162:0;;:::i;136396:118::-;;;:::i;143103:504::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;143103:504:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;143103:504:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;143103: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;143103:504:0;;-1:-1:-1;143103:504:0;-1:-1:-1;143103:504:0;:::i;26346:73::-;;;:::i;135060:99::-;;;:::i;123438:29::-;;;:::i;141375:130::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;141375:130:0;;;;;;;;:::i;140790:180::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140790:180:0;;;;;;;:::i;135888:375::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135888:375:0;;:::i;145245:402::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;145245:402:0;;;;;;;;;;;-1:-1:-1;;;;;145245:402:0;;:::i;139550:270::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;139550:270:0;;;;;;-1:-1:-1;;;;;139550:270:0;;:::i;138154:218::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;138154:218:0;;:::i;122337:37::-;;;:::i;25717:18::-;;;:::i;158816:641::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;158816:641:0;;;;:::i;123153:58::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;123153:58:0;;:::i;146399:1179::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;146399:1179:0;;:::i;154208:424::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;154208:424:0;;;;;;;:::i;123693:42::-;;;:::i;122851:27::-;;;:::i;139828:351::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;139828:351:0;;:::i;120070:210::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;120070:210:0;-1:-1:-1;;;;;120070:210:0;;:::i;135167:131::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135167:131:0;;:::i;121635:25::-;;;:::i;137056:112::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137056:112:0;;;;:::i;47466:109::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;47466:109:0;-1:-1:-1;;;;;47466:109:0;;:::i;150170:838::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;150170:838:0;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;150170:838:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;150170:838: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;150170:838:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;150170:838:0;;-1:-1:-1;150170:838:0;;-1:-1:-1;;;;;150170:838:0:i;132972:1394::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;132972:1394:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;140237:143::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140237:143:0;;:::i;26269:69::-;;;:::i;123474:28::-;;;:::i;148741:452::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;148741:452:0;;;;;;;;;;;;:::i;122052:29::-;;;:::i;121579:19::-;;;:::i;140666:116::-;25381:19;:17;:19::i;:::-;140748:17;:26;140666:116::o;141513:497::-;25381:19;:17;:19::i;:::-;141723:26;141734:14;141723:10;:26::i;:::-;141715:35;;;;;;141761:9;:24;;-1:-1:-1;;;;;;141761:24:0;;;141796:13;:30;;-1:-1:-1;;;;;;141796:30:0;;;-1:-1:-1;;;;;141796:30:0;;;;;;;141837:11;:38;;;;;;;;;;;;;;141886:6;:36;;;;;;;;;;;;;;141933:21;:69;;;;;;;;;;141513:497::o;122381:28::-;;;;:::o;122303:27::-;;;;:::o;121760:31::-;;;;:::o;137739:237::-;25381:19;:17;:19::i;:::-;137836:17;137828:26;;;;;;137865:6;;137905:18;;137865:59;;;-1:-1:-1;;;137865:59:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;137865:6:0;;;;:25;;:59;;;;;:6;;:59;;;;;;;;:6;;:59;;;5:2:-1;;;;30:1;27;20:12;5:2;137865:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;137935:18:0;:33;;;;-1:-1:-1;137739:237:0:o;135306:134::-;135392:11;;:40;;;-1:-1:-1;;;135392:40:0;;-1:-1:-1;;;;;135392:40:0;;;;;;;135365:7;135392:40;;;;;;;;135365:7;;135392:11;;:31;;:40;;;;;;;;;;;;;;;:11;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;135392:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;135392:40:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135392:40:0;;-1:-1:-1;135306:134:0;;;;:::o;156833:1017::-;156888:11;132423:26;132437:11;132423:13;:26::i;:::-;156954:13;156920:23;;;;:10;:23;;;;;:30;;;-1:-1:-1;;;156920:30:0;;;;:47;;;;;;;;;156912:70;;;;;-1:-1:-1;;;156912:70:0;;;;;;;;;;;;-1:-1:-1;;;156912:70:0;;;;;;;;;;;;;;;157001:23;;;;:10;:23;;;;;:41;;;:46;156993:76;;;;;-1:-1:-1;;;156993:76:0;;;;;;;;;;;;-1:-1:-1;;;156993:76:0;;;;;;;;;;;;;;;157106:12;;157082:21;157137:23;;;:10;:23;;;;;:32;;;:49;-1:-1:-1;157137:49:0;157129:84;;;;;-1:-1:-1;;;157129:84:0;;;;;;;;;;;;-1:-1:-1;;;157129:84:0;;;;;;;;;;;;;;;157226:14;157243:23;;;:10;:23;;;;;:30;157302:10;;157292:20;;;157284:29;;;;;;157326:26;157355:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;157355:39:0;157409:34;;157405:111;;157476:18;-1:-1:-1;;;;;157460:42:0;;:44;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;157460:44:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;157460:44:0;;;;157405:111;157625:23;;;;:10;:23;;;;;:39;;;157592:81;;157614:51;;:6;;:51;:10;:51;:::i;:::-;157668:1;157671;157592:14;:81::i;:::-;157686:23;;;;:10;:23;;;;;;:30;;;:46;;-1:-1:-1;;;;157686:46:0;-1:-1:-1;;;157686:46:0;;;157762:30;;;;;157803:6;;:39;;-1:-1:-1;;;157803:39:0;;;;;;;;-1:-1:-1;;;;;157762:30:0;;;157803:39;;;;;;;;157762:30;;157803:6;;;;;:18;;:39;;;;;157686:23;;157803:39;;;;;;157686:23;157803:6;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;157803:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;157803:39:0;;;;132460:1;;;;156833:1017;;:::o;122496:31::-;;;;:::o;121703:50::-;;;-1:-1:-1;;;;;121703:50:0;;:::o;137355:119::-;25381:19;:17;:19::i;:::-;137438:12;:28;137355:119::o;137482:146::-;25381:19;:17;:19::i;:::-;-1:-1:-1;;;;;137564:22:0;;137556:31;;;;;;137598:5;:22;;-1:-1:-1;;;;;;137598:22:0;-1:-1:-1;;;;;137598:22:0;;;;;;;;;;137482:146::o;123509:24::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;123509:24:0;;-1:-1:-1;123509:24:0;:::o;122106:38::-;;;;:::o;122885:60::-;;;;;;;;;;;;;;;;;;;:::o;136676:324::-;136739:4;136807:23;;;:10;:23;;;;;:30;;;;136856;;136905:41;;;;;136965:12;;136776:216;;-1:-1:-1;;;136807:30:0;;;;;;136856;136905:41;136776:12;:216::i;:::-;136756:236;136676:324;-1:-1:-1;;136676:324:0:o;147586:963::-;25783:17;:15;:17::i;:::-;147728:11;132423:26;132437:11;132423:13;:26::i;:::-;147760:23;;;;:10;:23;;;;;:41;;;:46;147752:71;;;;;-1:-1:-1;;;147752:71:0;;;;;;;;;;;;-1:-1:-1;;;147752:71:0;;;;;;;;;;;;;;;147840:10;;147836:96;;147867:53;147886:10;147906:4;147913:6;147867:18;:53::i;:::-;147944:27;147959:11;147944:14;:27::i;:::-;147988:12;147984:186;;;148037:23;;;;:10;:23;;;;;121569:1;148037:30;;;;148026:66;;121569:1;148026:42;;:6;;:42;:10;:42;:::i;:::-;:46;:66;:46;:66;:::i;:::-;148107:23;;;;:10;:23;;;;;121569:1;148107:30;;;:51;148017:75;-1:-1:-1;147984:186:0;148207:11;;148182:22;;148207:23;;148223:6;148207:23;:15;:23;:::i;:::-;148241:11;:28;;;148313:23;;;;:10;:23;;;;;:30;148182:48;;-1:-1:-1;148313:42:0;;148348:6;148313:42;:34;:42;:::i;:::-;148280:23;;;;:10;:23;;;;;:75;;;;148368:36;;148390:6;;148280:23;148368:14;:36::i;:::-;148417:6;;:34;;;-1:-1:-1;;;148417:34:0;;;;;;;;;;-1:-1:-1;;;;;148417:6:0;;;;:21;;:34;;;;;:6;;:34;;;;;;;;:6;;:34;;;5:2:-1;;;;30:1;27;20:12;5:2;148417:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;148462:6:0;;;148494:23;;;:10;:23;;;;;;:30;148462:79;;-1:-1:-1;;;148462:79:0;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;148462:6:0;;;;-1:-1:-1;148462:18:0;;-1:-1:-1;148462:79:0;;;;;;;;;;;:6;;:79;;;5:2:-1;;;;30:1;27;20:12;5:2;148462:79:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;148462:79:0;;;;132460:1;25811;147586:963;;;:::o;139345:104::-;46571:9;:7;:9::i;:::-;46563:18;;;;;;139423;;;;:7;;:18;;;;;:::i;:::-;;139345:104;:::o;144699:538::-;144757:11;132423:26;132437:11;132423:13;:26::i;:::-;144789:29;;;;:16;:29;;;;;:36;:41;144781:50;;;;;;144844:13;144860:23;;;:10;:23;;;;;:30;;;;144923:39;;;;;-1:-1:-1;;;144860:30:0;;;;;;144923:43;;;;:110;;-1:-1:-1;144987:23:0;;;;:10;:23;;;;;:41;;;:46;144923:110;:183;;;;-1:-1:-1;145065:13:0;145055:6;:23;;;;;;;;;:50;;;-1:-1:-1;145092:13:0;145082:6;:23;;;;;;;;;145055:50;144901:216;;;;;;145150:12;;145130:17;;145150:19;;145167:1;145150:19;:16;:19;:::i;:::-;145130:39;;145197:32;145206:11;145219:9;145197:8;:32::i;:::-;132460:1;;144699:538;;:::o;151016:3184::-;119894:9;;151231:7;;-1:-1:-1;;;;;119894:9:0;119880:10;:23;119872:32;;;;;;151275:12;;151382:26;;151251:21;;;;151421:44;;:::i;:::-;151523:7;:14;151509:44;;;151523:29;;;151509:44;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;151509:44:0;-1:-1:-1;151476:30:0;;;;:77;;;;151589:7;151564:32;;;;;;;;;;;;;;;;;;;;;151589:7;151564:32;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;151564:32:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;151564:22:0;;;:32;151636:1;151607:26;;;:30;151678:7;:14;151648:27;;;:44;151705:43;;:::i;:::-;151808:7;:14;151794:44;;;151808:29;;;151794:44;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;151794:44:0;-1:-1:-1;151759:32:0;;;:79;151856:9;151851:1809;151871:15;;;151851:1809;;;151908:14;151925:38;151945:8;151955:4;;151960:1;151955:7;;;;;;;;;;;;151925:38;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;151925:19:0;;-1:-1:-1;;151925:38:0:i;:::-;151908:55;;151994:7;-1:-1:-1;;;;;151984:17:0;:6;-1:-1:-1;;;;;151984:17:0;;151980:134;;;152090:8;;;151980:134;152143:7;-1:-1:-1;;;;;152134:16:0;:6;-1:-1:-1;;;;;152134:16:0;;152130:182;;;152291:5;;;152130:182;-1:-1:-1;;;;;152350:25:0;;152328:19;152350:25;;;:17;:25;;;;;;;;;152407:23;;;:10;:23;;;;;;:30;;152468;;;;152544:41;;;;;152513:72;;;152407:30;;-1:-1:-1;;;152468:30:0;;;;;152606:73;;152468:30;;152407;;152665:13;152606:12;:73::i;:::-;152602:1047;;;152777:23;;;;:10;:23;;;;;:39;;;152710:6;;-1:-1:-1;152710:6:0;;152756:73;;152822:6;;152756:61;;:16;;:61;:20;:61;:::i;:::-;:65;:73;:65;:73;:::i;:::-;152854:28;;152737:92;;-1:-1:-1;152854:33:0;152850:386;;153048:11;152986:10;:32;;;153019:10;:25;;;152986:59;;;;;;;;;;;;;;;;;:73;153082:25;;;:27;;;;;;152850:386;;;153172:44;153196:11;153209:6;153172:23;:44::i;:::-;153158:58;;152850:386;152602:1047;;;153271:13;153261:6;:23;;;;;;;;;153257:392;;;153520:11;153451;:30;;;153482:11;:34;;;153451:66;;;;;;;;;;;;;;;;;;:80;;;;153550:36;;;;;;;;153605:26;;;:28;;;;;;;153257:392;151851:1809;;;;;151888:3;;151851:1809;;;;153744:48;153768:11;153789:1;153744:23;:48::i;:::-;153730:62;;153825:367;153877:13;153909:8;153936:16;153971:9;153999:11;:30;;;154048:11;:34;;;154101:10;:32;;;154152:10;:25;;;153825:33;:367::i;:::-;153805:387;151016:3184;-1:-1:-1;;;;;;;;;;;;;151016:3184:0:o;121667:29::-;;;-1:-1:-1;;;;;121667:29:0;;:::o;122436:28::-;;;;:::o;122686:47::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;122686:47:0;;;;;;;;-1:-1:-1;;;122686:47:0;;;;;;;:::o;122740:52::-;;;;;;;;;;;;;:::o;135597:283::-;135665:7;135688:25;135717:50;135755:11;135717:37;:50::i;:::-;135785:23;;;;:10;:23;;;;;:40;;;135685:82;;-1:-1:-1;135785:87:0;;-1:-1:-1;121569:1:0;;135785:63;;135685:82;135785:63;:44;:63;:::i;:87::-;135778:94;135597:283;-1:-1:-1;;;135597:283:0:o;122002:25::-;;;;:::o;123781:37::-;;;;:::o;140978:389::-;25381:19;:17;:19::i;:::-;141171:20;141194:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;141194:39:0;141252:28;141244:37;;;;;;141292:67;;;-1:-1:-1;;;141292:67:0;;-1:-1:-1;;;;;141292:67:0;;;;;;;;;;;;;;;;;;;;;;:35;;;;;;:67;;;;;-1:-1:-1;;141292:67:0;;;;;;;;-1:-1:-1;141292:35:0;:67;;;5:2:-1;;;;30:1;27;20:12;142833:262:0;142894:7;-1:-1:-1;;;;;142918:20:0;;;;:56;;-1:-1:-1;142942:11:0;;:27;;;-1:-1:-1;;;142942:27:0;;-1:-1:-1;;;;;142942:27:0;;;;;;;;;:11;;;;;:21;;:27;;;;;;;;;;;;;;:11;:27;;;5:2:-1;;;;30:1;27;20:12;5:2;142942:27:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;142942:27:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;142942:27:0;:32;142918:56;142914:97;;;-1:-1:-1;142998:1:0;142991:8;;142914:97;143039:11;;:40;;;-1:-1:-1;;;143039:40:0;;-1:-1:-1;;;;;143039:40:0;;;;;;;143028:52;143039:40;;;;;;;;143028:10;;143039:11;;;;;:31;;:40;;;;;;;;;;;;;;:11;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;143039:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;143039:40:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;143039:40:0;143028:52;;143039:40;143028:52;;;;;;;;-1:-1:-1;143028:52:0;:59;;142833:262;-1:-1:-1;;142833:262:0:o;122151:32::-;;;;:::o;122192:33::-;;;;:::o;145910:481::-;25783:17;:15;:17::i;:::-;146152:18;;146124:25;:23;:25::i;:::-;:46;146116:72;;;;;-1:-1:-1;;;146116:72:0;;;;;;;;;;;;-1:-1:-1;;;146116:72:0;;;;;;;;;;;;;;;146217:10;;146207:6;:20;;146199:51;;;;;-1:-1:-1;;;146199:51:0;;;;;;;;;;;;-1:-1:-1;;;146199:51:0;;;;;;;;;;;;;;;146261:56;146279:4;146285:10;146297:11;146310:6;146261:17;:56::i;:::-;146328:55;146338:4;146344:6;146352:16;146370:12;146328:9;:55::i;:::-;;145910:481;;;;;:::o;144064:627::-;144317:10;144339:4;144317:27;144309:51;;;;;-1:-1:-1;;;144309:51:0;;;;;;;;;;;;-1:-1:-1;;;144309:51:0;;;;;;;;;;;;;;;144392:59;144410:11;144423;144436;144449:1;144392:17;:59::i;:::-;144462:35;144471:11;144484:12;;144462:8;:35::i;:::-;144510:22;144535:69;144545:11;144558:13;144573:16;144591:12;;144535:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;144535:9:0;;-1:-1:-1;;;144535:69:0:i;:::-;144615:6;;:68;;;-1:-1:-1;;;144615:68:0;;;;;;;;;;;;;;;;;;;;;;144510:94;;-1:-1:-1;;;;;;144615:6:0;;;;:24;;:68;;;;;:6;;:68;;;;;;;;:6;;:68;;;5:2:-1;;;;30:1;27;20:12;5:2;144615:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;144615:68:0;;;;144064:627;;;;;;;;:::o;123047:51::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;123047:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;123047:51:0;;;-1:-1:-1;;;123047:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;122648:29::-;;;;;;:::o;122271:25::-;;;;:::o;136522:146::-;136594:7;136621:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;136621:39:0;;136522:146::o;25202:29::-;;;;;;-1:-1:-1;;;;;25202:29:0;;:::o;134686:87::-;134757:8;;-1:-1:-1;;;;;134757:8:0;134686:87;;:::o;155002:1823::-;155106:8;;;155097:46;;;-1:-1:-1;;;155097:46:0;;;;155069:7;;155147:10;;-1:-1:-1;;;;;155106:8:0;;155097:44;;:46;;;;;;;;;;;155106:8;155097:46;;;5:2:-1;;;;30:1;27;20:12;5:2;155097:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;155097:46:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;155097:46:0;-1:-1:-1;;;;;155097:60:0;;155089:90;;;;;-1:-1:-1;;;155089:90:0;;;;;;;;;;;;-1:-1:-1;;;155089:90:0;;;;;;;;;;;;;;;155192:43;155238:38;:29;:17;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;155238:27:0;;-1:-1:-1;;;155238:29:0:i;:::-;:36;:38::i;:::-;155192:84;;155287:16;155314:20;155345:19;155375:9;155397:1281;155408:16;:23;155404:1;:27;155397:1281;;;155453:36;155492:28;:16;155509:1;155492:19;;;;;;;;;;;;;;:26;:28::i;:::-;155453:67;;155537:19;155559:21;:9;155569:1;155559:12;;;;;;;;;;;;;;:19;:21::i;:::-;155537:43;;155595:27;155610:11;155595:14;:27::i;:::-;155639:15;155657:21;:9;155667:1;155657:12;;;;;;;:21;155639:39;-1:-1:-1;155707:24:0;:11;155639:39;155707:24;:15;:24;:::i;:::-;155748:26;155777:23;;;:10;:23;;;;;:39;;;155693:38;;-1:-1:-1;;;;;;155777:39:0;155835:34;;155831:402;;155890:24;156006:23;;;:10;:23;;;;;;;;:30;;156063:39;;;;;155938:221;;-1:-1:-1;;;155938:221:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;155938:41:0;;;;;:221;;;;;;;;;;;155890:24;155938:41;:221;;;5:2:-1;;;;30:1;27;20:12;5:2;155938:221:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;155938:221:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;155938:221:0;;-1:-1:-1;156188:29:0;:7;155938:221;156188:29;:11;:29;:::i;:::-;156178:39;;155831:402;;156249:29;156281:23;;;:10;:23;;;;;:30;:43;;156316:7;156281:43;:34;:43;:::i;:::-;156339:23;;;;:10;:23;;;;;:54;;;156249:75;-1:-1:-1;156414:26:0;156410:257;;156461:35;156470:11;156483:12;;156461:8;:35::i;:::-;156410:257;;;156522:24;:9;156532:1;156522:12;;;;;;;;;;;;;;:22;:24::i;:::-;156518:149;;;156582:39;156599:21;156605:11;156618:1;156599:5;:21::i;:::-;156582:12;;:39;:16;:39;:::i;:::-;156640:11;;;;;156567:54;-1:-1:-1;156518:149:0;-1:-1:-1;;155433:3:0;;;;;-1:-1:-1;155397:1281:0;;-1:-1:-1;;155397:1281:0;;156717:69;156740:29;:11;156756:12;156740:29;:15;:29;:::i;:::-;156732:38;;156773:9;156772:10;;156784:1;156717:14;:69::i;:::-;-1:-1:-1;156806:11:0;155002:1823;-1:-1:-1;;;;;;155002:1823:0:o;138380:542::-;25381:19;:17;:19::i;:::-;138615:13;;138643:260;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;138643:260:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;138588:326:0;;-1:-1:-1;;;;;138615:13:0;;138588:12;:326::i;:::-;138380:542;;;:::o;134841:118::-;134923:11;;:28;;;-1:-1:-1;;;134923:28:0;;;;;;;;;;134896:7;;-1:-1:-1;;;;;134923:11:0;;:19;;:28;;;;;;;;;;;;;;:11;:28;;;5:2:-1;;;;30:1;27;20:12;142062:150:0;25783:17;:15;:17::i;:::-;142153:51;142171:4;142177:10;142189:11;142202:1;142153:17;:51::i;142220:605::-;142456:38;;;142467:10;142456:38;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;142456:38:0;;;;;;;142446:49;;;;;;142519:16;;-1:-1:-1;;;142446:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:65;;;;:49;;142512:5;;142519:16;;142537:5;;142446:97;;;;;;;;;;;;;-1:-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;142446:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;142446:97:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;142446:97:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;142446:97:0;142424:162;;;;;-1:-1:-1;;;142424:162:0;;;;;;;;;;;;-1:-1:-1;;;142424:162:0;;;;;;;;;;;;;;;142653:10;142597:22;142641:23;;;:11;:23;;;;;;142622:43;;:14;;:43;:18;:43;:::i;:::-;142597:68;;142676:37;142686:10;142698:14;142676:9;:37::i;:::-;142736:10;142724:23;;;;:11;:23;;;;;:40;;;142775:42;;142802:14;142775;:42::i;145655:247::-;145818:4;145796:11;132672:30;132690:11;132672:17;:30::i;:::-;145842:5;;:52;;;-1:-1:-1;;;145842:52:0;;-1:-1:-1;;;;;145842:52:0;;;;;;;145880:4;145842:52;;;;;;;;;;;;:5;;;;;:18;;:52;;;;;;;;;;;;;;:5;;:52;;;5:2:-1;;;;30:1;27;20:12;5:2;145842:52:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;145842:52:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;145842:52:0;;145655:247;-1:-1:-1;;;;;145655:247:0:o;121886:22::-;;;;:::o;47149:140::-;46571:9;:7;:9::i;:::-;46563:18;;;;;;47232:6;;47211:40;;47248:1;;-1:-1:-1;;;;;47232:6:0;;47211:40;;47248:1;;47211:40;47262:6;:19;;-1:-1:-1;;;;;;47262:19:0;;;47149:140::o;121813:27::-;;;;:::o;122607:34::-;;;;:::o;122954:46::-;;;;;;;;;;;;;:::o;121605:23::-;;;-1:-1:-1;;;;;121605:23:0;;:::o;123902:36::-;;;;:::o;121938:32::-;;;;:::o;154640:354::-;154739:7;154717:11;132672:30;132690:11;132672:17;:30::i;:::-;154759:27;154774:11;154759:14;:27::i;:::-;154799:19;154821:23;;;:10;:23;;;;;:40;;;:64;;121569:1;154821:64;:44;:64;:::i;:::-;154896:23;;;;:10;:23;;;;;121569:1;154896:40;;;;:61;154799:86;-1:-1:-1;;154640:354:0;;;;:::o;135448:141::-;135515:7;135542:23;;;:10;:23;;;;;:39;;;;135448:141::o;136271:117::-;136354:26;;136271:117;:::o;122238:26::-;;;;:::o;149936:226::-;150037:11;132672:30;132690:11;132672:17;:30::i;:::-;150103:23;;;;:10;:23;;;;;:39;;;:51;;150147:6;150103:51;:43;:51;:::i;:::-;150061:23;;;;:10;:23;;;;;;:39;;:93;;;;-1:-1:-1;;149936:226:0:o;123407:24::-;;;;;;-1:-1:-1;;;;;123407:24:0;;:::o;46359:79::-;46424:6;;-1:-1:-1;;;;;46424:6:0;46359:79;:::o;134374:255::-;134475:38;;;;;;;;;;;;;;;;134558:15;134601:10;-1:-1:-1;;;;;134601:20:0;;;;134374:255;:::o;134967:85::-;135032:12;;134967:85;:::o;137226:121::-;25381:19;:17;:19::i;:::-;137304:35;137313:11;137326:12;;137304:8;:35::i;:::-;137226:121;:::o;123592:32::-;;;;:::o;148557:176::-;148621:11;132423:26;132437:11;132423:13;:26::i;:::-;148645:27;148660:11;148645:14;:27::i;:::-;148683:42;148701:11;148714:10;148683:17;:42::i;119632:24::-;;;-1:-1:-1;;;;;119632:24:0;;:::o;143615:441::-;25783:17;:15;:17::i;:::-;143798:13;;143826:211;;;;;;;;;;;;;;;144017:4;143826:211;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;143826:211:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;143771:277:0;;-1:-1:-1;;;;;143798:13:0;;143771:12;:277::i;123220:31::-;;;;:::o;140388:270::-;25381:19;:17;:19::i;:::-;140476:6;;140524:13;;140476:62;;;-1:-1:-1;;;140476:62:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;140476:6:0;;;;:29;;:62;;;;;:6;;:62;;;;;;;;:6;;:62;;;5:2:-1;;;;30:1;27;20:12;5:2;140476:62:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;140476:62:0;;;;121395:3;140557:16;:38;;140549:58;;;;;-1:-1:-1;;;140549:58:0;;;;;;;;;;;;-1:-1:-1;;;140549:58:0;;;;;;;;;;;;;;;140618:13;:32;140388:270::o;138967:370::-;46571:9;:7;:9::i;:::-;46563:18;;;;;;139101:13;;139129:189;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;139129:189:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;139074:255:0;;-1:-1:-1;;;;;139101:13:0;;139074:12;:255::i;149201:520::-;149289:11;132672:30;132690:11;132672:17;:30::i;:::-;149326:1;149317:6;:10;149313:142;;;149399:17;;;;149391:52;;;;;-1:-1:-1;;;149391:52:0;;;;;;;;;;;;-1:-1:-1;;;149391:52:0;;;;;;;;;;;;;;;149467:28;149482:6;149490:1;149493;149467:14;:28::i;:::-;149522:1;149512:6;:11;149508:206;;149540:62;149573:11;149594:6;149540:32;:62::i;:::-;149508:206;;;149635:67;149668:11;149689:6;-1:-1:-1;;149689:11:0;149635:32;:67::i;137984:162::-;25381:19;:17;:19::i;:::-;138081:12;138073:21;;;;;;138105:23;:33;137984:162::o;136396:118::-;136485:14;:21;136396:118;:::o;143103:504::-;25783:17;:15;:17::i;:::-;143323:13;;143351:237;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;143296:303;;-1:-1:-1;;;;;143323:13:0;;-1:-1:-1;;;143392:58:0;143469:11;;143499:6;;143524:17;;143560:13;;;;143351:237;;143560:13;;;;143351:237;1:33:-1;99:1;81:16;;;74:27;143351:237:0;;;-1:-1:-1;;137:4;117:14;;;113:30;;157:16;;;26:21;;;22:32;;;6:49;;143351:237:0;-1:-1:-1;49:4;25:18;;61:17;;-1:-1;;;;;;143351:237:0;;;;-1:-1:-1;;;;;182:15;;;179:29;;;;160:49;;;-1:-1;143296:12:0;;-1:-1:-1;;;;;;143296:303:0:i;:::-;143103:504;;;;;:::o;26346:73::-;25381:19;:17;:19::i;:::-;26397:14;:12;:14::i;:::-;26346:73::o;135060:99::-;135135:16;;135060:99;:::o;123438:29::-;;;;:::o;141375:130::-;25381:19;:17;:19::i;:::-;141462:35;141477:11;141490:6;141462:14;:35::i;140790:180::-;25381:19;:17;:19::i;:::-;140895:10;:24;;;;140930:14;:32;140790:180::o;135888:375::-;135955:7;136014:23;;;:10;:23;;;;;:41;;;135955:7;;136010:152;;136100:50;136138:11;136100:37;:50::i;:::-;-1:-1:-1;136077:73:0;-1:-1:-1;136010:152:0;136179:23;;;;:10;:23;;;;;121569:1;136179:30;;;;:76;;121569:1;136179:52;;136214:16;136179:52;:34;:52;:::i;145245:402::-;145376:4;145415:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;145415:39:0;145458:10;145415:53;;:134;;-1:-1:-1;145498:8:0;;;145489:46;;;-1:-1:-1;;;145489:46:0;;;;145539:10;;-1:-1:-1;;;;;145498:8:0;;;;145489:44;;:46;;;;;;;;;;;;;145498:8;145489:46;;;5:2:-1;;;;30:1;27;20:12;5:2;145489:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;145489:46:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;145489:46:0;-1:-1:-1;;;;;145489:60:0;;145415:134;145393:195;;;;;-1:-1:-1;;;145393:195:0;;;;;;;;;;;;-1:-1:-1;;;145393:195:0;;;;;;;;;;;;;;;145606:5;;:33;;;-1:-1:-1;;;145606:33:0;;-1:-1:-1;;;;;145606:33:0;;;;;;;;;;;;;;;:5;;;;;:14;;:33;;;;;;;;;;;;;;:5;;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;145606:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;145606:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;145606:33:0;;145245:402;-1:-1:-1;;;;145245:402:0:o;139550:270::-;25381:19;:17;:19::i;:::-;139735:4;-1:-1:-1;;;;;139680:60:0;139696:18;-1:-1:-1;;;;;139680:41:0;;:43;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;139680:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;139680:43:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;139680:43:0;-1:-1:-1;;;;;139680:60:0;;139672:69;;;;;;139752:23;;;;:10;:23;;;;;;:39;;:60;;-1:-1:-1;;;;;;139752:60:0;-1:-1:-1;;;;;139752:60:0;;;;;;;;;139550:270::o;138154:218::-;25381:19;:17;:19::i;:::-;138246:14;138238:23;;;;;;138272:6;;138306:17;;138272:52;;;-1:-1:-1;;;138272:52:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;138272:6:0;;;;:22;;:52;;;;;:6;;:52;;;;;;;;:6;;:52;;;5:2:-1;;;;30:1;27;20:12;5:2;138272:52:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;138335:17:0;:29;;;;-1:-1:-1;138154:218:0:o;122337:37::-;;;;:::o;25717:18::-;;;;;;:::o;158816:641::-;158928:10;158888:19;158910:29;;;:17;:29;;;;;;;;;159003:23;;;:10;:23;;;;;;:30;;;;159052;;159101:41;;;;;159161:12;;158972:216;;-1:-1:-1;;;159003:30:0;;;;;;159052;159101:41;158972:12;:216::i;:::-;158950:279;;;;;-1:-1:-1;;;158950:279:0;;;;;;;;;;;;-1:-1:-1;;;158950:279:0;;;;;;;;;;;;;;;159242:20;159265:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;159265:39:0;159323:28;159315:63;;;;;-1:-1:-1;;;159315:63:0;;;;;;;;;;;;-1:-1:-1;;;159315:63:0;;;;;;;;;;;;;;;159391:58;;;-1:-1:-1;;;159391:58:0;;;;;;;;;;;-1:-1:-1;;;;;159391:46:0;;;;;:58;;;;;-1:-1:-1;;159391:58:0;;;;;;;-1:-1:-1;159391:46:0;:58;;;5:2:-1;;;;30:1;27;20:12;5:2;159391:58:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;159391:58:0;;;;158816:641;;;:::o;123153:58::-;;;;;;;;;;;;;:::o;146399:1179::-;146460:11;132423:26;132437:11;132423:13;:26::i;:::-;146484:25;146512:23;;;:10;:23;;;;;:41;;;146647:21;;;;;:97;;-1:-1:-1;146732:12:0;;146711:16;;146689:39;;:17;;:39;:21;:39;:::i;:::-;:55;;146647:97;:167;;;;-1:-1:-1;146799:15:0;146765:23;;;;:10;:23;;;;;:30;;;-1:-1:-1;;;146765:30:0;;;;:49;;;;;;;;;;146647:167;146625:200;;;;;;146838:14;146855:23;;;:10;:23;;;;;:30;146921:11;;146855:30;;146838:14;146921:23;;146855:30;146921:23;:15;:23;:::i;:::-;146955:11;:28;;;146896:48;-1:-1:-1;147067:42:0;147085:11;147098:10;147067:17;:42::i;:::-;147122:11;;:29;;;-1:-1:-1;;;147122:29:0;;;;;;;;;;-1:-1:-1;;;;;147122:11:0;;;;:16;;:29;;;;;:11;;:29;;;;;;;;:11;;:29;;;5:2:-1;;;;30:1;27;20:12;5:2;147122:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;147197:1:0;147164:23;;;:10;:23;;;;;:34;;;147209:32;;;:36;;;;147256:30;;;:43;;-1:-1:-1;;;;;;147256:43:0;;;-1:-1:-1;;147312:49:0;:74;147397:30;;:48;;-1:-1:-1;;;;147397:48:0;-1:-1:-1;;;147397:48:0;;;-1:-1:-1;147458:34:0;147473:10;147485:6;147458:14;:34::i;:::-;147503:6;;:67;;;-1:-1:-1;;;147503:67:0;;147522:10;147503:67;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;147503:6:0;;;;:18;;:67;;;;;:6;;:67;;;;;;;;:6;;:67;;;5:2:-1;;;;30:1;27;20:12;154208:424:0;154306:11;132423:26;132437:11;132423:13;:26::i;:::-;154330:27;154345:11;154330:14;:27::i;:::-;154397:13;;154425:188;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;154425:188:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;154370:254:0;;-1:-1:-1;;;;;154397:13:0;;154370:12;:254::i;123693:42::-;;;;:::o;122851:27::-;;;;;;:::o;139828:351::-;25381:19;:17;:19::i;:::-;139930:1;139917:10;:14;139909:23;;;;;;139943:6;;139984:7;;139943:49;;;-1:-1:-1;;;139943:49:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;139943:6:0;;;;:28;;:49;;;;;:6;;:49;;;;;;;;:6;;:49;;;5:2:-1;;;;30:1;27;20:12;5:2;139943:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;140003:7:0;:20;;;-1:-1:-1;140034:16:0;:29;;;140090:17;140013:10;140105:1;140090:17;:14;:17;:::i;:::-;140074:13;:33;;;140140:12;;:31;;;:16;:31;:::i;:::-;140118:19;:53;-1:-1:-1;139828:351:0:o;120070:210::-;46571:9;:7;:9::i;:::-;46563:18;;;;;;-1:-1:-1;;;;;120153:26:0;;120145:35;;;;;;120213:9;;120196:41;;-1:-1:-1;;;;;120196:41:0;;;;120213:9;;120196:41;;120213:9;;120196:41;120248:9;:24;;-1:-1:-1;;;;;;120248:24:0;-1:-1:-1;;;;;120248:24:0;;;;;;;;;;120070:210::o;135167:131::-;135233:7;135260:23;;;:10;:23;;;;;:30;;135167:131::o;121635:25::-;;;-1:-1:-1;;;;;121635:25:0;;:::o;137056:112::-;25381:19;:17;:19::i;:::-;137133:17;:27;;-1:-1:-1;;137133:27:0;;;;;;;;;;137056:112::o;47466:109::-;46571:9;:7;:9::i;:::-;46563:18;;;;;;47539:28;47558:8;47539:18;:28::i;150170:838::-;150258:11;132423:26;132437:11;132423:13;:26::i;:::-;150282:14;150299:33;150319:12;150299:19;:33::i;:::-;150367:12;;150456:17;;150343:21;150415:36;;;:23;:36;;;;;;150282:50;;-1:-1:-1;150367:12:0;;150415:59;;;:40;:59;:::i;:::-;150398:13;:76;;150390:100;;;;;-1:-1:-1;;;150390:100:0;;;;;;;;;;;;-1:-1:-1;;;150390:100:0;;;;;;;;;;;;;;;150503:21;150527:23;;;:10;:23;;;;;;;;:30;;;;;150600:6;;:72;;-1:-1:-1;;;150600:72:0;;;;;;;;-1:-1:-1;;;;;150527:30:0;;;150600:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;150527:30;;150600:6;;;;;:22;;150527:23;;:30;;150600: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;150600:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;150600:72:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;;;;;;150685:32:0;;;;;;;:17;:32;;;;;;;;-1:-1:-1;;150685:57:0;;150753:25;;;;;;;;;:39;;;150803:23;;;:10;:23;;;;;;:30;;:39;;-1:-1:-1;;;;;;150803:39:0;;;;;;-1:-1:-1;150853:36:0;150703:13;150771:6;150853:13;:36::i;:::-;-1:-1:-1;150948:36:0;;;;:23;:36;;;;;;:52;;;;-1:-1:-1;;;150170:838:0:o;132972:1394::-;63701:6;;;;63700:7;63692:34;;;;;-1:-1:-1;;;63692:34:0;;;;;;;;;;;;-1:-1:-1;;;63692:34:0;;;;;;;;;;;;;;;63737:6;:13;;-1:-1:-1;;63737:13:0;63746:4;63737:13;;;133314:26;133325:14;133314:10;:26::i;:::-;133306:61;;;;;-1:-1:-1;;;133306:61:0;;;;;;;;;;;;-1:-1:-1;;;133306:61:0;;;;;;;;;;;;;;;133378:13;:30;;-1:-1:-1;;;;;;133378:30:0;;;-1:-1:-1;;;;;133378:30:0;;;;;;;;;;-1:-1:-1;133419:37:0;;-1:-1:-1;;;;;;133419:37:0;133378:30;133419:37;;;;;;;133467:8;:20;;;;;;;;;;133498:9;:22;;;;;;;;;;133531:5;:22;;;;;;;;;;133564:11;:38;;;;;;;;;;133613:6;:36;;;;;;;;;;133660:21;:69;;;;;;;;;;;;;;133740:26;133759:6;133740:18;:26::i;:::-;-1:-1:-1;;133799:5:0;133779:16;:26;-1:-1:-1;;133846:1:0;133831:12;:16;;;133868:3;133858:7;:13;;;133925:16;133905:17;:36;133991:6;133977:10;:21;;;134027:14;:25;134107:4;134081:23;:30;134142:3;134122:17;:23;134179:1;134158:18;:22;134197:10;:14;;;134238:11;134222:13;:27;134280:13;:18;134334:17;:24;;-1:-1:-1;;134334:24:0;;;;;;-1:-1:-1;;;;;132972:1394:0:o;140237:143::-;25381:19;:17;:19::i;:::-;140339:12;;:33;;140356:15;140339:33;:16;:33;:::i;26269:69::-;25381:19;:17;:19::i;:::-;26318:12;:10;:12::i;123474:28::-;;;-1:-1:-1;;;;;123474:28:0;;:::o;148741:452::-;148961:1;148945:13;:17;148937:47;;;;;-1:-1:-1;;;148937:47:0;;;;;;;;;;;;-1:-1:-1;;;148937:47:0;;;;;;;;;;;;;;;149011:27;;;;:10;:27;;;;;;:43;;;148995:91;;-1:-1:-1;;;148995:91:0;;149067:10;148995:91;;;;;;;;;;;;-1:-1:-1;;;;;149011:43:0;;;;148995:71;;:91;;;;;;;;;;;149011:27;:43;148995:91;;;5:2:-1;;;;30:1;27;20:12;5:2;148995:91:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;149113:25:0;;;;:10;:25;;;;;;:41;;;149097:88;;-1:-1:-1;;;149097:88:0;;149166:10;149097:88;;;;;;;;;;;;-1:-1:-1;;;;;149113:41:0;;;;-1:-1:-1;149097:68:0;;:88;;;;;149113:25;;149097:88;;;;;;149113:25;:41;149097:88;;;5:2:-1;;;;30:1;27;20:12;122052:29:0;;;;:::o;121579:19::-;;;-1:-1:-1;;;;;121579:19:0;;:::o;25428:182::-;25525:10;;;;;-1:-1:-1;;;;;25525:10:0;25503;:33;25481:121;;;;-1:-1:-1;;;25481:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27457:274;27517:4;-1:-1:-1;;;;;27538:21:0;;27534:66;;-1:-1:-1;27583:5:0;27576:12;;27534:66;-1:-1:-1;27667:20:0;27715:8;;;27457:274::o;132477:131::-;132553:11;;:32;;;-1:-1:-1;;;132553:32:0;;;;;;;;;;132589:10;;-1:-1:-1;;;;;132553:11:0;;:19;;:32;;;;;;;;;;;;;;:11;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;132553:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;132553:32:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;132553:32:0;-1:-1:-1;;;;;132553:46:0;;132545:55;;;;;3325:150;3383:7;3415:5;;;3439:6;;;;3431:15;;;;;157858:950;157996:16;157992:809;;158097:1;158088:6;:10;158084:245;;;158143:14;:21;:42;;158177:6;158143:42;:25;:42;:::i;:::-;158119:14;:66;158084:245;;;158220:1;158211:6;:10;158207:122;;;158266:14;:21;:47;;158300:11;;;;158266:47;:25;:47;:::i;:::-;158242:14;:71;158207:122;158363:1;158349:11;:15;158345:285;;;158414:26;;:52;;158453:11;158414:52;:30;:52;:::i;:::-;158385:26;:81;158345:285;;;158506:1;158492:11;:15;158488:142;;;158557:26;;:57;;158596:16;;;;158557:57;:30;:57;:::i;:::-;158528:26;:86;157992:809;;;158662:34;;;;:21;:34;;;;;:51;;;;;;-1:-1:-1;158728:46:0;:61;;;;;;157858:950;;;:::o;159836:304::-;160004:4;160038:1;160029:6;:10;:75;;;;-1:-1:-1;160044:22:0;;;:59;;;160090:13;160070:17;:33;160044:59;160029:102;;;;-1:-1:-1;160118:13:0;160108:6;:23;;;;;;;;;160029:102;160021:111;159836:304;-1:-1:-1;;;;;159836:304:0:o;25828:85::-;25888:6;;;;25887:7;25879:26;;;;;-1:-1:-1;;;25879:26:0;;;;;;;;;;;;-1:-1:-1;;;25879:26:0;;;;;;;;;;;;;;174849:218;174989:5;;:45;;;-1:-1:-1;;;174989:45:0;;-1:-1:-1;;;;;174989:45:0;;;;;;;;;;;;;;;;;;;;;;:5;;;;;:18;;:45;;;;;;;;;;;;;;:5;;:45;;;5:2:-1;;;;30:1;27;20:12;5:2;174989:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;174989:45:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;174989:45:0;174981:78;;;;;-1:-1:-1;;;174981:78:0;;;;;;;;;;;;-1:-1:-1;;;174981:78:0;;;;;;;;;;;;;;167238:140;167302:68;167326:11;167339:14;;167355;;167302:23;:68::i;3087:150::-;3145:7;3178:1;3173;:6;;3165:15;;;;;;-1:-1:-1;3203:5:0;;;3087:150::o;172688:1104::-;172909:27;172924:11;172909:14;:27::i;:::-;172949:14;172966:23;;;:10;:23;;;;;:30;;173027:20;172977:11;173027:7;:20::i;:::-;173060:23;;;;:10;:23;;;;;:41;;;:53;;;173203:39;;;;173285;;;;;173007:40;;-1:-1:-1;173203:39:0;-1:-1:-1;;;;;173285:39:0;173339:32;;173335:107;;173404:18;-1:-1:-1;;;;;173388:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;173388:42:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;173388:42:0;;;;173335:107;173468:23;;;;:10;:23;;;;;:30;;;173454:45;;-1:-1:-1;;;;;173468:30:0;173454:13;:45::i;:::-;173510:41;173528:11;173541:9;173510:17;:41::i;:::-;173564:19;173599:12;;173586:9;:25;;:41;;173618:9;173586:41;;;173614:1;173586:41;173564:63;;173638:69;173672:16;173662:6;173655:33;173653:36;;-1:-1:-1;;173695:11:0;173638:14;:69::i;:::-;173720:6;;:64;;;-1:-1:-1;;;173720:64:0;;-1:-1:-1;;;;;173720:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:6;;;;;:21;;:64;;;;;:6;;:64;;;;;;;:6;;:64;;;5:2:-1;;;;30:1;27;20:12;5:2;173720:64:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;173720:64:0;;;;172688: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;160148:606::-;160287:32;;:::i;:::-;160369:7;:23;;;160344:7;:22;;;:48;:104;;;;;160442:6;-1:-1:-1;;;;;160396:52:0;:7;:18;;;160415:7;:22;;;160396:42;;;;;;;;;;;;;;-1:-1:-1;;;;;160396:52:0;;;160344:104;160337:348;;;160526:17;:61;160544:7;:18;;;160563:7;:22;;;160544:42;;;;;;;;;;;;;;-1:-1:-1;;;;;160526:61:0;-1:-1:-1;;;;;160526:61:0;;;;;;;;;;;;;160465:7;:26;;;160492:7;:30;;;160465:58;;;;;;;;;;;;;;;;;;:122;;;;160602:32;;;;;;;;160649:22;;;:24;;;;;;;160337:348;;;-1:-1:-1;;160697:22:0;;;:24;;;;;;:22;160148:606::o;163333:1818::-;163752:14;:21;163704:7;;163812:38;163848:1;163812:31;163841:1;163812:24;163752:21;163834:1;163812:24;:21;:24;:::i;:::-;:28;:31;:28;:31;:::i;:38::-;163792:16;:58;;163784:90;;;;;-1:-1:-1;;;163784:90:0;;;;;;;;;;;;-1:-1:-1;;;163784:90:0;;;;;;;;;;;;;;;163887:14;163904:78;163931:13;163946:16;163964:17;163904:26;:78::i;:::-;163887:95;;163995:22;164020:49;121395:3;164020:25;164031:13;;164020:6;:10;;:25;;;;:::i;:49::-;-1:-1:-1;;;;;164101:27:0;;164080:18;164101:27;;;:17;:27;;;;;;;;;164171:22;;;:10;:22;;;;;;164223:16;;;;163995:74;;-1:-1:-1;164101:27:0;;164223:36;;163995:74;164223:36;:20;:36;:::i;:::-;164204:16;;;:55;164351:16;:28;;;164392:25;164433:90;164452:70;164505:16;164452:48;121441:6;164452:26;:6;164463:14;164452:26;:10;:26;:::i;:::-;:30;:48;:30;:48;:::i;:70::-;164433:14;;;:90;:18;:90;:::i;:::-;164392:131;;164679:88;164704:18;164724:23;164749:17;164679:24;:88::i;:::-;164837:14;:34;;;164995:94;165020:21;165043:26;164854:17;164995:24;:94::i;:::-;165102:17;:15;:17::i;:::-;-1:-1:-1;165137:6:0;;163333:1818;-1:-1:-1;;;;;;;;;;;;;163333:1818:0:o;169632:704::-;169749:23;169842;;;:10;:23;;;;;:30;;169932:39;;;;;169749:23;;169842:30;169749:23;;169912:60;;169842:30;;169912:60;:19;:60;:::i;:::-;169983:22;170025:23;;;:10;:23;;;;;:45;;;170008:14;;169883:89;;-1:-1:-1;170008:62:0;;170101:227;170036:11;170182:15;170216:60;121441:6;170216:38;170008:62;169883:89;170216:38;:18;:38;:::i;:60::-;170295:18;170101:32;:227::i;:::-;170081:247;;;;;;;169632:704;;;:::o;175075:383::-;175246:14;;175239:3;:21;;175231:47;;;;;-1:-1:-1;;;175231:47:0;;;;;;;;;;;;-1:-1:-1;;;175231:47:0;;;;;;;;;;;;;;;175289:66;175308:4;175322;175329:25;:3;175337:16;175329:25;:7;:25;:::i;:::-;175289:18;:66::i;:::-;175385:16;;:25;;175406:3;175385:25;:20;:25;:::i;:::-;175366:16;:44;175421:6;;:29;;;-1:-1:-1;;;175421:29:0;;-1:-1:-1;;;;;175421:29:0;;;;;;;;;;;;;;;:6;;;;;:18;;:29;;;;;:6;;:29;;;;;;;:6;;:29;;;5:2:-1;;;;30:1;27;20:12;5:2;175421:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;175421:29:0;;;;175075:383;;;;:::o;171012:1668::-;171172:7;171192:14;171209:33;171229:12;171209:19;:33::i;:::-;171277:12;;171322:10;;171365:6;;171409:11;;171192:50;;-1:-1:-1;171277:12:0;;171322:10;;-1:-1:-1;;;;;171365:6:0;;171253:21;;171409:23;;171425:6;171409:23;:15;:23;:::i;:::-;171384:48;;171457:14;171443:11;:28;;;;171510:638;;;;;;;;171584:6;171510:638;;;;121569:1;171510:638;;;;171622:13;171510:638;;;;171669:1;171510:638;;;;171695:1;171510:638;;;;171719:6;-1:-1:-1;;;;;171510:638:0;;;;;171757:16;:137;;171890:3;171757:137;;;171793:21;;171853:8;;;171793:69;;;-1:-1:-1;;;171793:69:0;;;;;;;;-1:-1:-1;;;;;171793:69:0;;;;;;;171853:8;;;171793:69;;;;;:21;;;:28;;:69;;;;;;;;;;;;;;;:21;;:69;;;5:2:-1;;;;30:1;27;20:12;5:2;171793:69:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;171793:69:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;171793:69:0;171757:137;-1:-1:-1;;;;;171510:638:0;;;;;171917:13;171510:638;;171961:1;171510:638;;;;;;;;;;;;;;121569:1;171510:638;;;;;;;;;;;;;;172122:14;;171510:638;;;;;171484:23;;;:10;:23;;;;;;:664;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;171484:664:0;;;-1:-1:-1;;;;;;171484:664:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;171484:664:0;;;;-1:-1:-1;;;171484:664:0;;;;;;;;;;;;;;-1:-1:-1;171484:664:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;172161:36:0;;;:23;:36;;;;;;:52;;;172224:11;;:35;;-1:-1:-1;;;172224:35:0;;-1:-1:-1;;;;;172224:35:0;;;;;;;;;;;;;;;:11;;;;;:16;;:35;;;;;;;;;;-1:-1:-1;172224:11:0;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;172224:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;;;;;;172272:25:0;;;;;;:17;:25;;;;;:39;;;172322:36;;-1:-1:-1;172344:6:0;;172353:1;;172322:14;:36::i;:::-;172450:13;172407:16;:29;172424:11;172407:29;;;;;;;;;;;:40;;:56;;;;172474:7;-1:-1:-1;;;;;172474:17:0;;172492:6;172500:12;172514:11;172527:13;172542:6;172550:14;172474:91;;;;;;;;;;;;;-1:-1:-1;;;;;172474:91:0;-1:-1:-1;;;;;172474: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;172474:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;172474:91:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;172474:91:0;;;;172589:18;172605:1;172589:11;:15;;:18;;;;:::i;:::-;172576:10;:31;172620:21;172634:6;172620:13;:21::i;:::-;-1:-1:-1;172661:11:0;;171012:1668;-1:-1:-1;;;;;;;;171012: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;170344:660::-;170423:7;170472:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;170472:39:0;170526:34;;170522:109;;170593:18;-1:-1:-1;;;;;170577:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;170577:42:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;170577:42:0;;;;170522:109;170667:12;;170725:34;170667:12;170743:15;170725:34;:17;:34;:::i;:::-;170690:23;;;;:10;:23;;;;;;:32;;;;:69;;;;170770:30;;;:46;;-1:-1:-1;;;;170770:46:0;-1:-1:-1;;;170770:46:0;;;170827:6;;;170872:30;;;170827:76;;-1:-1:-1;;;170827:76:0;;;;;;;;;;;;;;-1:-1:-1;;;;;170872:30:0;;;170827:76;;;;;;:6;;;:16;;:76;;;;;170690:23;;170827:76;;;;;170690:23;170827:6;:76;;;5:2:-1;;;;30:1;27;20:12;5:2;170827:76:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;170956:23:0;;;;:10;:23;;;;;:39;;;;170921:30;;:75;;-1:-1:-1;170921:30:0;:75;:34;:75;:::i;26553:892::-;26918:1;26898;26869:9;26863:16;26839:4;26828:9;26824:20;26801:4;26776:5;26771:3;26767:15;26736:198;26960:14;27007:4;27001:11;27049:4;27046:1;27041:3;27026:28;27252:6;27276:66;;;;27403:4;27398:3;27391:17;27276:66;27318:4;27313:3;27306:17;175466:166;175553:16;;:28;;175574:6;175553:28;:20;:28;:::i;:::-;175534:16;:47;175592:6;;:32;;;-1:-1:-1;;;175592:32:0;;-1:-1:-1;;;;;175592:32:0;;;;;;;;;;;;;;;:6;;;;;:18;;:32;;;;;:6;;:32;;;;;;;:6;;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;175592:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;174690:151:0;174778:5;;:35;;;-1:-1:-1;;;174778:35:0;;-1:-1:-1;;;;;174778:35:0;;;;;;;;;;;;;;;:5;;;;;:14;;:35;;;;;;;;;;;;;;:5;;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;174778:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;174778:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;174778:35:0;174770:63;;;;;-1:-1:-1;;;174770:63:0;;;;;;;;;;;;-1:-1:-1;;;174770:63:0;;;;;;;;;;;;;;132730:170;132810:23;;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;132810:39:0;132853:10;132810:53;132802:90;;;;;-1:-1:-1;;;132802:90:0;;;;;;;;;;;;;;;;;;;;;;;;;;;174182:500;174272:14;174289:23;;;:10;:23;;;;;121569:1;174289:30;;;;:54;;;:34;:54;:::i;:::-;174379:22;;174272:71;;-1:-1:-1;174379:34:0;;174272:71;174379:34;:26;:34;:::i;:::-;174354:22;:59;174424:23;;;;:10;:23;;;;;121569:1;174424:30;;;:51;174534:14;;174486:45;;;;:62;174559:37;174574:13;174589:6;174559:14;:37::i;:::-;174607:6;;174651:22;;174607:67;;;-1:-1:-1;;;174607:67:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;174607:6:0;;;;:22;;:67;;;;;:6;;:67;;;;;;;;:6;;:67;;;5:2:-1;;;;30:1;27;20:12;149729:199:0;149869:23;;;;:10;:23;;;;;:39;;;:51;;149913:6;149869:51;:43;:51;:::i;:::-;149827:23;;;;:10;:23;;;;;;:39;;:93;;;;-1:-1:-1;149729:199:0:o;25984:58::-;26029:5;26020:14;;-1:-1:-1;;26020:14:0;;;25984: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;47725:187::-;-1:-1:-1;;;;;47799:22:0;;47791:31;;;;;;47859:6;;47838:38;;-1:-1:-1;;;;;47838:38:0;;;;47859:6;;47838:38;;47859:6;;47838:38;47887:6;:17;;-1:-1:-1;;;;;;47887:17:0;-1:-1:-1;;;;;47887:17:0;;;;;;;;;;47725:187::o;159510:318::-;159579:7;159607:3;:10;159621:2;159607:16;159599:36;;;;;-1:-1:-1;;;159599:36:0;;;;;;;;;;;;-1:-1:-1;;;159599:36:0;;;;;;;;;;;;;;;159687:14;;;;;;-1:-1:-1;;;;;159723:20:0;;;;;;:54;;-1:-1:-1;;;;;;159747:25:0;;;;;;:17;:25;;;;;;:30;159723:54;159715:81;;;;;-1:-1:-1;;;159715:81:0;;;;;;;;;;;;-1:-1:-1;;;159715:81:0;;;;;;;;;;;;;;176098:150;176180:25;176194:10;176180:13;:25::i;:::-;176216:24;176230:9;176216:13;:24::i;25921:55::-;25955:6;:13;;-1:-1:-1;;25955:13:0;25964:4;25955:13;;;25921:55::o;165584:1646::-;165749:29;165781:23;;;:10;:23;;;;;:45;;;165918;;;165914:1158;;;165980:23;166006;;;:10;:23;;;;;:30;;166077:39;;;;;166135:19;;166131:930;;166175:26;166204:36;:15;166224;166204:36;:19;:36;:::i;:::-;166175:65;;166259:419;166320:11;166354:15;166392;166430:229;166484:11;166522:18;166567:21;166615;166430:27;:229::i;:::-;166259:38;:419::i;:::-;166131:930;;;;166719:326;166766:11;166800:226;166854:11;166892:15;166934:21;166982;166800:27;:226::i;:::-;166719:24;:326::i;:::-;165914:1158;;;167108:21;167088:17;:41;167084:139;;;167146:23;;;;:10;:23;;;;;:45;;:65;;;165584:1646;;;;:::o;176256:569::-;176346:7;:14;;;176323:20;;-1:-1:-1;;176400:16:0;;176392:25;;;;;;;;;;;;;;;;;176435:7;:25;;-1:-1:-1;;;;;176392:25:0;;;;-1:-1:-1;176435:7:0;-1:-1:-1;;176443:16:0;;;176435:25;;;;;;;;;;;;;;;176428:32;;-1:-1:-1;;;;;;176428:32:0;;;-1:-1:-1;;176566:16:0;;176549:223;176584:5;;176549:223;;176629:14;-1:-1:-1;;;;;176615:28:0;:10;-1:-1:-1;;;;;176615:28:0;;176611:74;;;176664:5;;176611:74;176733:7;176745:1;176741;:5;176733:14;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;176733:14:0;176749:10;176714:7;176726:1;176722;:5;176714:14;;;;;;;;;;;;;;;;;176701:59;;-1:-1:-1;;;;;;176701:59:0;-1:-1:-1;;;;;176701:59:0;;;;;;;;;;;-1:-1:-1;;;176591:3:0;176549:223;;;-1:-1:-1;;;176801:16:0;;176784:33;:7;176801:16;176784:33;:::i;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;;;;;160762:2563;161426:23;;161480:17;;160926:7;;161426:23;160926:7;161532:69;161426:23;161541:13;161426:23;161541:35;;;;;161578:22;;161532:8;:69::i;:::-;161508:93;;161677:1;161661:13;:17;:55;;;;;161699:17;;161682:13;:34;;161661:55;161657:613;;;161737:17;;:22;161733:464;;161859:13;123582:3;161888:21;;161876:9;:33;:56;;;;;;161859:74;;161994:13;161974:17;;:33;161970:212;;;162077:18;;;;161970:212;;;162157:5;162144:18;;;;161970:212;161733:464;;162225:17;:33;;;161657:613;162282:14;162329:19;162313:13;:35;162309:777;;;162450:27;;162555:150;162588:116;123582:3;162588:90;162602:75;162641:1;-1:-1:-1;;162604:17:0;;162603:35;;:39;162450:27;162602:45;:75::i;:::-;162588:9;;:90;:13;:90;:::i;:116::-;162555:28;:9;162569:13;162555:28;:13;:28;:::i;:150::-;162546:159;-1:-1:-1;162809:57:0;162827:38;:13;162845:19;162827:38;:17;:38;:::i;:::-;162809:13;;:57;:17;:57;:::i;:::-;162793:73;-1:-1:-1;162971:103:0;162985:88;123582:3;162985:62;163018:28;162985;:9;162999:13;162985:28;:13;:28;:::i;:88::-;162971:9;;:103;:13;:103;:::i;:::-;162959:115;;162309:777;;163157:65;163168:53;163201:19;163168:28;:13;163186:9;163168:28;:17;:28;:::i;:53::-;163157:6;;:65;:10;:65;:::i;:::-;163148:74;-1:-1:-1;163242:51:0;163275:17;163242:28;163148:74;163253:16;163242:28;:10;:28;:::i;:51::-;163233:60;160762:2563;-1:-1:-1;;;;;;;;160762:2563:0:o;165159:417::-;165375:14;;165343:29;165400:169;165424:23;165420:1;:27;165400:169;;;165469:88;165493:18;165512:1;165493:21;;;;;;;;;;;;;;165516;165539:17;165469:23;:88::i;:::-;165449:3;;165400:169;;173800:374;173871:12;;173847:21;173914:20;173871:12;173932:1;173914:20;:17;:20;:::i;:::-;173894:40;;173947:26;;:::i;:::-;-1:-1:-1;173976:32:0;;;;:21;:32;;;;;;;;173947:61;;;;;;;;;;;;;;;;;;;;;;;;;;174019:54;;173947:61;174019:14;:54::i;:::-;-1:-1:-1;174093:36:0;;;;:21;:36;;;;;174086:43;;;;;;;;;174142:12;:24;173800:374::o;168772:852::-;168970:7;;169003:23;168999:69;;-1:-1:-1;169051:1:0;;-1:-1:-1;169051:1:0;169043:13;;168999:69;169080:23;169106:51;169138:18;169106:27;:15;169126:6;169106:27;:19;:27;:::i;:51::-;169230:22;169255:23;;;:10;:23;;;;;:38;;;169080:77;;-1:-1:-1;169308:18:0;;169304:193;;169361:124;169399:71;121347:3;169399:47;169431:14;169399:27;:6;169410:15;169399:27;:10;:27;:::i;:71::-;169361:15;;:124;:19;:124;:::i;:::-;169343:142;;169304:193;169509:24;169536:27;:6;169547:15;169536:27;:10;:27;:::i;:::-;169582:15;;-1:-1:-1;169509:54:0;;-1:-1:-1;;;168772:852:0;;;;;;;;:::o;175640:450::-;175702:7;27:10:-1;;39:1;23:18;;45:23;;-1:-1;175702:23:0;;;;;;;-1:-1:-1;;;;;;175702:23:0;-1:-1:-1;;;;;175702:23:0;;;;;175755:14;-1:-1:-1;;175755:18:0;;175813:189;175820:5;;175813:189;;175847:14;175864:7;175876:1;175872;:5;175864:14;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;175864:14:0;;;;-1:-1:-1;175897:18:0;;;;175893:64;;;175936:5;;;175893:64;175984:6;175971:7;175979:1;175971:10;;;;;;;;;;;;;;;;;:19;;-1:-1:-1;;;;;;175971:19:0;-1:-1:-1;;;;;175971:19:0;;;;;;;;;;-1:-1:-1;;;175827:3:0;175813:189;;;176023:9;176018:1;:14;176014:69;;176062:9;176049:7;176057:1;176049:10;;;;;;;;;;;;;;;;:22;;;;;-1:-1:-1;;;;;176049:22:0;;;;;-1:-1:-1;;;;;176049:22:0;;;;;;175640:450;;;:::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;167386:391::-;167600:7;167645:45;;;167708:61;121441:6;167708:39;167645:45;167727:19;167708:39;:18;:39;:::i;168008:756::-;168205:26;168234:36;:15;168254;168234:36;:19;:36;:::i;:::-;168205:65;;168282:23;168307:24;168348:90;168381:11;168394:15;168411:6;168419:18;168348:32;:90::i;:::-;168281:157;;-1:-1:-1;168281:157:0;-1:-1:-1;168455:20:0;;168451:158;;168535:23;;;;:10;:23;;;;;:40;;;:62;;168580:16;168535:62;:44;:62;:::i;:::-;168492:23;;;;:10;:23;;;;;:40;;:105;168451:158;168625:19;;168621:136;;168694:23;;;;:10;:23;;;;;:30;;;:51;;168729:15;168694:51;:34;:51;:::i;:::-;168661:23;;;;:10;:23;;;;;:30;;:84;168008:756;;;;;;;:::o;167785:215::-;167879:10;;167875:118;;167939:23;;;;:10;:23;;;;;:30;;;:42;;167974:6;167939:42;:34;:42;:::i;:::-;167906:23;;;;:10;:23;;;;;:30;;:75;167785: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;131680:45148::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;131680:45148:0;-1:-1:-1;;;;;131680:45148:0;;;;;;;;;;;-1:-1:-1;131680:45148:0;;;;;;;-1:-1:-1;131680:45148:0;;;-1:-1:-1;131680:45148:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;;131680:45148:0;;;;;;;;;;;;;;;;;;;;;;;;
Swarm Source
bzzr://431c6a8057326866c4c2118b555375b4c31f1897330945422ed25bde58989ddc
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.