Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
StakeManager
Compiler Version
v0.5.17+commit.d19bba13
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2020-10-27
*/
// 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: 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: solidity-rlp/contracts/RLPReader.sol
/*
* @author Hamdi Allam [email protected]
* Please reach out with any questions or concerns
*/
pragma solidity ^0.5.0;
library RLPReader {
uint8 constant STRING_SHORT_START = 0x80;
uint8 constant STRING_LONG_START = 0xb8;
uint8 constant LIST_SHORT_START = 0xc0;
uint8 constant LIST_LONG_START = 0xf8;
uint8 constant WORD_SIZE = 32;
struct RLPItem {
uint len;
uint memPtr;
}
struct Iterator {
RLPItem item; // Item that's being iterated over.
uint nextPtr; // Position of the next item in the list.
}
/*
* @dev Returns the next element in the iteration. Reverts if it has not next element.
* @param self The iterator.
* @return The next element in the iteration.
*/
function next(Iterator memory self) internal pure returns (RLPItem memory) {
require(hasNext(self));
uint ptr = self.nextPtr;
uint itemLength = _itemLength(ptr);
self.nextPtr = ptr + itemLength;
return RLPItem(itemLength, ptr);
}
/*
* @dev Returns true if the iteration has more elements.
* @param self The iterator.
* @return true if the iteration has more elements.
*/
function hasNext(Iterator memory self) internal pure returns (bool) {
RLPItem memory item = self.item;
return self.nextPtr < item.memPtr + item.len;
}
/*
* @param item RLP encoded bytes
*/
function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) {
uint memPtr;
assembly {
memPtr := add(item, 0x20)
}
return RLPItem(item.length, memPtr);
}
/*
* @dev Create an iterator. Reverts if item is not a list.
* @param self The RLP item.
* @return An 'Iterator' over the item.
*/
function iterator(RLPItem memory self) internal pure returns (Iterator memory) {
require(isList(self));
uint ptr = self.memPtr + _payloadOffset(self.memPtr);
return Iterator(self, ptr);
}
/*
* @param item RLP encoded bytes
*/
function rlpLen(RLPItem memory item) internal pure returns (uint) {
return item.len;
}
/*
* @param item RLP encoded bytes
*/
function payloadLen(RLPItem memory item) internal pure returns (uint) {
return item.len - _payloadOffset(item.memPtr);
}
/*
* @param item RLP encoded list in bytes
*/
function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) {
require(isList(item));
uint items = numItems(item);
RLPItem[] memory result = new RLPItem[](items);
uint memPtr = item.memPtr + _payloadOffset(item.memPtr);
uint dataLen;
for (uint i = 0; i < items; i++) {
dataLen = _itemLength(memPtr);
result[i] = RLPItem(dataLen, memPtr);
memPtr = memPtr + dataLen;
}
return result;
}
// @return indicator whether encoded payload is a list. negate this function call for isData.
function isList(RLPItem memory item) internal pure returns (bool) {
if (item.len == 0) return false;
uint8 byte0;
uint memPtr = item.memPtr;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < LIST_SHORT_START)
return false;
return true;
}
/** RLPItem conversions into data types **/
// @returns raw rlp encoding in bytes
function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) {
bytes memory result = new bytes(item.len);
if (result.length == 0) return result;
uint ptr;
assembly {
ptr := add(0x20, result)
}
copy(item.memPtr, ptr, item.len);
return result;
}
// any non-zero byte is considered true
function toBoolean(RLPItem memory item) internal pure returns (bool) {
require(item.len == 1);
uint result;
uint memPtr = item.memPtr;
assembly {
result := byte(0, mload(memPtr))
}
return result == 0 ? false : true;
}
function toAddress(RLPItem memory item) internal pure returns (address) {
// 1 byte for the length prefix
require(item.len == 21);
return address(toUint(item));
}
function toUint(RLPItem memory item) internal pure returns (uint) {
require(item.len > 0 && item.len <= 33);
uint offset = _payloadOffset(item.memPtr);
uint len = item.len - offset;
uint result;
uint memPtr = item.memPtr + offset;
assembly {
result := mload(memPtr)
// shfit to the correct location if neccesary
if lt(len, 32) {
result := div(result, exp(256, sub(32, len)))
}
}
return result;
}
// enforces 32 byte length
function toUintStrict(RLPItem memory item) internal pure returns (uint) {
// one byte prefix
require(item.len == 33);
uint result;
uint memPtr = item.memPtr + 1;
assembly {
result := mload(memPtr)
}
return result;
}
function toBytes(RLPItem memory item) internal pure returns (bytes memory) {
require(item.len > 0);
uint offset = _payloadOffset(item.memPtr);
uint len = item.len - offset; // data length
bytes memory result = new bytes(len);
uint destPtr;
assembly {
destPtr := add(0x20, result)
}
copy(item.memPtr + offset, destPtr, len);
return result;
}
/*
* Private Helpers
*/
// @return number of payload items inside an encoded list.
function numItems(RLPItem memory item) private pure returns (uint) {
if (item.len == 0) return 0;
uint count = 0;
uint currPtr = item.memPtr + _payloadOffset(item.memPtr);
uint endPtr = item.memPtr + item.len;
while (currPtr < endPtr) {
currPtr = currPtr + _itemLength(currPtr); // skip over an item
count++;
}
return count;
}
// @return entire rlp item byte length
function _itemLength(uint memPtr) private pure returns (uint) {
uint itemLen;
uint byte0;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < STRING_SHORT_START)
itemLen = 1;
else if (byte0 < STRING_LONG_START)
itemLen = byte0 - STRING_SHORT_START + 1;
else if (byte0 < LIST_SHORT_START) {
assembly {
let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is
memPtr := add(memPtr, 1) // skip over the first byte
/* 32 byte word size */
let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len
itemLen := add(dataLen, add(byteLen, 1))
}
}
else if (byte0 < LIST_LONG_START) {
itemLen = byte0 - LIST_SHORT_START + 1;
}
else {
assembly {
let byteLen := sub(byte0, 0xf7)
memPtr := add(memPtr, 1)
let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length
itemLen := add(dataLen, add(byteLen, 1))
}
}
return itemLen;
}
// @return number of bytes until the data
function _payloadOffset(uint memPtr) private pure returns (uint) {
uint byte0;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < STRING_SHORT_START)
return 0;
else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START))
return 1;
else if (byte0 < LIST_SHORT_START) // being explicit
return byte0 - (STRING_LONG_START - 1) + 1;
else
return byte0 - (LIST_LONG_START - 1) + 1;
}
/*
* @param src Pointer to source
* @param dest Pointer to destination
* @param len Amount of memory to copy from the source
*/
function copy(uint src, uint dest, uint len) private pure {
if (len == 0) return;
// copy as many word sizes as possible
for (; len >= WORD_SIZE; len -= WORD_SIZE) {
assembly {
mstore(dest, mload(src))
}
src += WORD_SIZE;
dest += WORD_SIZE;
}
// left over bytes. Mask is used to remove unwanted bytes from the word
uint mask = 256 ** (WORD_SIZE - len) - 1;
assembly {
let srcpart := and(mload(src), not(mask)) // zero out src
let destpart := and(mload(dest), mask) // retrieve the bytes
mstore(dest, or(destpart, srcpart))
}
}
}
// File: contracts/common/lib/BytesLib.sol
pragma solidity ^0.5.2;
library BytesLib {
function concat(bytes memory _preBytes, bytes memory _postBytes)
internal
pure
returns (bytes memory)
{
bytes memory tempBytes;
assembly {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// Store the length of the first bytes array at the beginning of
// the memory for tempBytes.
let length := mload(_preBytes)
mstore(tempBytes, length)
// Maintain a memory counter for the current write location in the
// temp bytes array by adding the 32 bytes for the array length to
// the starting location.
let mc := add(tempBytes, 0x20)
// Stop copying when the memory counter reaches the length of the
// first bytes array.
let end := add(mc, length)
for {
// Initialize a copy counter to the start of the _preBytes data,
// 32 bytes into its memory.
let cc := add(_preBytes, 0x20)
} lt(mc, end) {
// Increase both counters by 32 bytes each iteration.
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
// Write the _preBytes data into the tempBytes memory 32 bytes
// at a time.
mstore(mc, mload(cc))
}
// Add the length of _postBytes to the current length of tempBytes
// and store it as the new length in the first 32 bytes of the
// tempBytes memory.
length := mload(_postBytes)
mstore(tempBytes, add(length, mload(tempBytes)))
// Move the memory counter back from a multiple of 0x20 to the
// actual end of the _preBytes data.
mc := end
// Stop copying when the memory counter reaches the new combined
// length of the arrays.
end := add(mc, length)
for {
let cc := add(_postBytes, 0x20)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
// Update the free-memory pointer by padding our last write location
// to 32 bytes: add 31 bytes to the end of tempBytes to move to the
// next 32 byte block, then round down to the nearest multiple of
// 32. If the sum of the length of the two arrays is zero then add
// one before rounding down to leave a blank 32 bytes (the length block with 0).
mstore(
0x40,
and(
add(add(end, iszero(add(length, mload(_preBytes)))), 31),
not(31) // Round down to the nearest 32 bytes.
)
)
}
return tempBytes;
}
function slice(bytes memory _bytes, uint256 _start, uint256 _length)
internal
pure
returns (bytes memory)
{
require(_bytes.length >= (_start + _length));
bytes memory tempBytes;
assembly {
switch iszero(_length)
case 0 {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// The first word of the slice result is potentially a partial
// word read from the original array. To read it, we calculate
// the length of that partial word and start copying that many
// bytes into the array. The first word we copy will start with
// data we don't care about, but the last `lengthmod` bytes will
// land at the beginning of the contents of the new array. When
// we're done copying, we overwrite the full first word with
// the actual length of the slice.
let lengthmod := and(_length, 31)
// The multiplication in the next line is necessary
// because when slicing multiples of 32 bytes (lengthmod == 0)
// the following copy loop was copying the origin's length
// and then ending prematurely not copying everything it should.
let mc := add(
add(tempBytes, lengthmod),
mul(0x20, iszero(lengthmod))
)
let end := add(mc, _length)
for {
// The multiplication in the next line has the same exact purpose
// as the one above.
let cc := add(
add(
add(_bytes, lengthmod),
mul(0x20, iszero(lengthmod))
),
_start
)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(tempBytes, _length)
//update free-memory pointer
//allocating the array padded to 32 bytes like the compiler does now
mstore(0x40, and(add(mc, 31), not(31)))
}
//if we want a zero-length slice let's just return a zero-length array
default {
tempBytes := mload(0x40)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
// Pad a bytes array to 32 bytes
function leftPad(bytes memory _bytes) internal pure returns (bytes memory) {
// may underflow if bytes.length < 32. Hence using SafeMath.sub
bytes memory newBytes = new bytes(SafeMath.sub(32, _bytes.length));
return concat(newBytes, _bytes);
}
function toBytes32(bytes memory b) internal pure returns (bytes32) {
require(b.length >= 32, "Bytes array should atleast be 32 bytes");
bytes32 out;
for (uint256 i = 0; i < 32; i++) {
out |= bytes32(b[i] & 0xFF) >> (i * 8);
}
return out;
}
function toBytes4(bytes memory b) internal pure returns (bytes4 result) {
assembly {
result := mload(add(b, 32))
}
}
function fromBytes32(bytes32 x) internal pure returns (bytes memory) {
bytes memory b = new bytes(32);
for (uint256 i = 0; i < 32; i++) {
b[i] = bytes1(uint8(uint256(x) / (2**(8 * (31 - i)))));
}
return b;
}
function fromUint(uint256 _num) internal pure returns (bytes memory _ret) {
_ret = new bytes(32);
assembly {
mstore(add(_ret, 32), _num)
}
}
function toUint(bytes memory _bytes, uint256 _start)
internal
pure
returns (uint256)
{
require(_bytes.length >= (_start + 32));
uint256 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x20), _start))
}
return tempUint;
}
function toAddress(bytes memory _bytes, uint256 _start)
internal
pure
returns (address)
{
require(_bytes.length >= (_start + 20));
address tempAddress;
assembly {
tempAddress := div(
mload(add(add(_bytes, 0x20), _start)),
0x1000000000000000000000000
)
}
return tempAddress;
}
}
// File: contracts/common/lib/ECVerify.sol
pragma solidity ^0.5.2;
library ECVerify {
function ecrecovery(bytes32 hash, bytes memory sig)
public
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)
public
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)
public
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() {
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/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
//
// 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/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.2;
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 stake(
uint256 amount,
uint256 heimdallFee,
bool acceptDelegation,
bytes calldata signerPubkey
) external;
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,
bytes memory sigs
) public returns (uint256);
function updateValidatorState(uint256 validatorId, int256 amount) public;
function ownerOf(uint256 tokenId) public view returns (address);
function slash(bytes memory slashingInfoList) public returns (uint256);
function validatorStake(uint256 validatorId) public view returns (uint256);
function epoch() public view returns (uint256);
function withdrawalDelay() public view returns (uint256);
}
// File: contracts/staking/validatorShare/IValidatorShare.sol
pragma solidity ^0.5.2;
// note this contract interface is only for stakeManager use
contract IValidatorShare {
function withdrawRewardsValidator() external returns (uint256);
function addProposerBonus(uint256 _rewards, uint256 valStake) public;
function withdrawRewards() public;
function unstakeClaimTokens() public;
function getLiquidRewards(address user) public view returns (uint256);
function getActiveAmount() external view returns (uint256);
function owner() public view returns (address);
function restake() public;
function updateRewards(
uint256 _reward,
uint256 _totalStake,
uint256 validatorStake
) external returns (uint256);
function unlockContract() external returns (uint256);
function lockContract() external returns (uint256);
function drain(
address token,
address payable destination,
uint256 amount
) external;
function slash(uint256 valPow, 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: 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);
}
function logUpdateCommissionRate(
uint256 validatorId,
uint256 newCommissionRate,
uint256 oldCommissionRate
) public onlyValidatorContract(validatorId) {
emit UpdateCommissionRate(
validatorId,
newCommissionRate,
oldCommissionRate
);
}
}
// 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/ProxyStorage.sol
pragma solidity ^0.5.2;
contract ProxyStorage is Ownable {
address internal proxyTo;
}
// 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 {
function proxyType() external pure returns (uint256 proxyTypeId) {
// Upgradeable proxy
proxyTypeId = 2;
}
function implementation() external view returns (address);
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)
}
}
}
}
// 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)
}
}
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/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: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
pragma solidity ^0.5.2;
/**
* @title Standard ERC20 token
*
* @dev Implementation of the basic standard token.
* https://eips.ethereum.org/EIPS/eip-20
* Originally based on code by FirstBlood:
* https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
*
* This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for
* all accounts just by listening to said events. Note that this isn't required by the specification, and other
* compliant implementations may not do it.
*/
contract ERC20 is IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowed;
uint256 private _totalSupply;
/**
* @dev Total number of tokens in existence
*/
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
/**
* @dev Gets the balance of the specified address.
* @param owner The address to query the balance of.
* @return A uint256 representing the amount owned by the passed address.
*/
function balanceOf(address owner) public view returns (uint256) {
return _balances[owner];
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param owner address The address which owns the funds.
* @param spender address The address which will spend the funds.
* @return A uint256 specifying the amount of tokens still available for the spender.
*/
function allowance(address owner, address spender) public view returns (uint256) {
return _allowed[owner][spender];
}
/**
* @dev Transfer token to a specified address
* @param to The address to transfer to.
* @param value The amount to be transferred.
*/
function transfer(address to, uint256 value) public returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
* Beware that changing an allowance with this method brings the risk that someone may use both the old
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
*/
function approve(address spender, uint256 value) public returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
/**
* @dev Transfer tokens from one address to another.
* Note that while this function emits an Approval event, this is not required as per the specification,
* and other compliant implementations may not emit the event.
* @param from address The address which you want to send tokens from
* @param to address The address which you want to transfer to
* @param value uint256 the amount of tokens to be transferred
*/
function transferFrom(address from, address to, uint256 value) public returns (bool) {
_transfer(from, to, value);
_approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
return true;
}
/**
* @dev Increase the amount of tokens that an owner allowed to a spender.
* approve should be called when _allowed[msg.sender][spender] == 0. To increment
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* Emits an Approval event.
* @param spender The address which will spend the funds.
* @param addedValue The amount of tokens to increase the allowance by.
*/
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
return true;
}
/**
* @dev Decrease the amount of tokens that an owner allowed to a spender.
* approve should be called when _allowed[msg.sender][spender] == 0. To decrement
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* Emits an Approval event.
* @param spender The address which will spend the funds.
* @param subtractedValue The amount of tokens to decrease the allowance by.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
return true;
}
/**
* @dev Transfer token for a specified addresses
* @param from The address to transfer from.
* @param to The address to transfer to.
* @param value The amount to be transferred.
*/
function _transfer(address from, address to, uint256 value) internal {
require(to != address(0));
_balances[from] = _balances[from].sub(value);
_balances[to] = _balances[to].add(value);
emit Transfer(from, to, value);
}
/**
* @dev Internal function that mints an amount of the token and assigns it to
* an account. This encapsulates the modification of balances such that the
* proper events are emitted.
* @param account The account that will receive the created tokens.
* @param value The amount that will be created.
*/
function _mint(address account, uint256 value) internal {
require(account != address(0));
_totalSupply = _totalSupply.add(value);
_balances[account] = _balances[account].add(value);
emit Transfer(address(0), account, value);
}
/**
* @dev Internal function that burns an amount of the token of a given
* account.
* @param account The account whose tokens will be burnt.
* @param value The amount that will be burnt.
*/
function _burn(address account, uint256 value) internal {
require(account != address(0));
_totalSupply = _totalSupply.sub(value);
_balances[account] = _balances[account].sub(value);
emit Transfer(account, address(0), value);
}
/**
* @dev Approve an address to spend another addresses' tokens.
* @param owner The address that owns the tokens.
* @param spender The address that will spend the tokens.
* @param value The number of tokens that can be spent.
*/
function _approve(address owner, address spender, uint256 value) internal {
require(spender != address(0));
require(owner != address(0));
_allowed[owner][spender] = value;
emit Approval(owner, spender, value);
}
/**
* @dev Internal function that burns an amount of the token of a given
* account, deducting from the sender's allowance for said account. Uses the
* internal burn function.
* Emits an Approval event (reflecting the reduced allowance).
* @param account The account whose tokens will be burnt.
* @param value The amount that will be burnt.
*/
function _burnFrom(address account, uint256 value) internal {
_burn(account, value);
_approve(account, msg.sender, _allowed[account][msg.sender].sub(value));
}
}
// File: contracts/common/tokens/ERC20NonTransferable.sol
pragma solidity ^0.5.2;
contract ERC20NonTransferable is ERC20 {
function _transfer(
address from,
address to,
uint256 value
) internal {
revert("Disabled");
}
}
// 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/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/validatorShare/ValidatorShare.sol
pragma solidity ^0.5.2;
contract ValidatorShare is IValidatorShare, ERC20NonTransferable, 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;
uint256 public commissionRate;
//last checkpoint where validator updated commission rate
uint256 public lastCommissionUpdate;
uint256 public minAmount = 10**18;
// deprecated
uint256 public __totalStake;
uint256 public rewardPerShare;
uint256 public activeAmount;
bool public delegation = true;
uint256 public withdrawPool;
uint256 public withdrawShares;
// deprecated
mapping(address => uint256) __amountStaked;
mapping(address => DelegatorUnbond) public unbonds;
mapping(address => uint256) public initalRewardPerShare;
modifier onlyValidator() {
require(stakeManager.ownerOf(validatorId) == msg.sender, "not validator");
_;
}
// 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);
minAmount = 10**18;
delegation = true;
}
function updateCommissionRate(uint256 newCommissionRate) external onlyValidator {
uint256 epoch = stakeManager.epoch();
uint256 _lastCommissionUpdate = lastCommissionUpdate;
require( // withdrawalDelay == dynasty
(_lastCommissionUpdate.add(stakeManager.withdrawalDelay()) <= epoch) || _lastCommissionUpdate == 0, // For initial setting of commission rate
"Commission rate update cooldown period"
);
require(newCommissionRate <= MAX_COMMISION_RATE, "Commission rate should be in range of 0-100");
stakingLogger.logUpdateCommissionRate(validatorId, newCommissionRate, commissionRate);
commissionRate = newCommissionRate;
lastCommissionUpdate = epoch;
}
function updateRewards(uint256 reward, uint256 checkpointStakePower, uint256 validatorStake)
external
onlyOwner
returns (uint256)
{
uint256 combinedStakePower = validatorStake.add(activeAmount); // validator + delegation stake power
uint256 rewards = combinedStakePower.mul(reward).div(checkpointStakePower);
_updateRewards(rewards, validatorStake, combinedStakePower);
return combinedStakePower;
}
function addProposerBonus(uint256 rewards, uint256 validatorStake) public onlyOwner {
uint256 combinedStakePower = validatorStake.add(activeAmount);
_updateRewards(rewards, validatorStake, combinedStakePower);
}
function _updateRewards(uint256 rewards, uint256 validatorStake, uint256 combinedStakePower) internal {
uint256 _validatorRewards = validatorStake.mul(rewards).div(combinedStakePower);
// add validator commission from delegation rewards
if (commissionRate > 0) {
_validatorRewards = _validatorRewards.add(
rewards.sub(_validatorRewards).mul(commissionRate).div(MAX_COMMISION_RATE)
);
}
validatorRewards = validatorRewards.add(_validatorRewards);
uint256 delegatorsRewards = rewards.sub(_validatorRewards);
uint256 totalShares = totalSupply();
if (totalShares > 0) {
rewardPerShare = rewardPerShare.add(
delegatorsRewards.mul(REWARD_PRECISION).div(totalShares)
);
}
}
function withdrawRewardsValidator() external onlyOwner returns (uint256) {
uint256 _validatorRewards = validatorRewards;
validatorRewards = 0;
return _validatorRewards;
}
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 exchangeRate() public view returns (uint256) {
uint256 totalShares = totalSupply();
uint256 precision = _getRatePrecision();
return
totalShares == 0
? precision
: activeAmount.mul(precision).div(totalShares);
}
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 buyVoucher(uint256 _amount, uint256 _minSharesToMint) public {
_buyVoucher(_amount, _minSharesToMint);
}
function _buyVoucher(uint256 _amount, uint256 _minSharesToMint) internal returns(uint256) {
_withdrawAndTransferReward(msg.sender);
uint256 amountToDeposit = _buyShares(_amount, _minSharesToMint, msg.sender);
require(stakeManager.delegationDeposit(validatorId, amountToDeposit, msg.sender), "deposit failed");
return amountToDeposit;
}
function _getTotalStake(address user) internal 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 restake() public {
_restake();
}
function _restake() internal returns(uint256) {
uint256 liquidReward = _withdrawReward(msg.sender);
require(liquidReward >= minAmount, "Too small rewards to restake");
uint256 amountRestaked = _buyShares(liquidReward, 0, msg.sender);
if (liquidReward > amountRestaked) {
// return change to the user
require(stakeManager.transferFunds(validatorId, liquidReward - amountRestaked, msg.sender), "Insufficent rewards");
stakingLogger.logDelegatorClaimRewards(validatorId, msg.sender, liquidReward - amountRestaked);
}
(uint256 totalStaked, ) = _getTotalStake(msg.sender);
stakingLogger.logDelegatorRestaked(validatorId, msg.sender, totalStaked);
return amountRestaked;
}
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 = _amount.sub(_amount % rate.mul(shares).div(precision));
activeAmount = activeAmount.add(_amount);
stakeManager.updateValidatorState(validatorId, int256(_amount));
StakingInfo logger = stakingLogger;
logger.logShareMinted(validatorId, user, _amount, shares);
logger.logStakeUpdate(validatorId);
return _amount;
}
function _reduceActiveStake(uint256 activeStakeReduce) private {
activeAmount = activeAmount.sub(activeStakeReduce);
}
function _reduceWithdrawPool(uint256 withdrawPoolReduce) private {
withdrawPool = withdrawPool.sub(withdrawPoolReduce);
}
function sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn) public {
// 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));
_reduceActiveStake(claimAmount);
uint256 _withdrawPoolShare = claimAmount.mul(precision).div(withdrawExchangeRate());
withdrawPool = withdrawPool.add(claimAmount);
withdrawShares = withdrawShares.add(_withdrawPoolShare);
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 _withdrawReward(address user) private returns(uint256) {
uint256 liquidRewards = getLiquidRewards(user);
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 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));
_reduceActiveStake(amount);
stakingLogger.logShareBurned(validatorId, user, amount, shares);
stakingLogger.logStakeUpdate(validatorId);
stakingLogger.logDelegatorUnstaked(validatorId, user, amount);
}
function migrateIn(address user, uint256 amount) external onlyOwner {
_buyShares(amount, 0, user);
}
function getLiquidRewards(address user) public view returns (uint256) {
uint256 shares = balanceOf(user);
if (shares == 0) {
return 0;
}
return rewardPerShare.sub(initalRewardPerShare[user]).mul(shares).div(REWARD_PRECISION);
}
function unstakeClaimTokens() public {
_claimUnstakedTokens();
}
function _claimUnstakedTokens() internal returns(uint256) {
DelegatorUnbond memory unbond = unbonds[msg.sender];
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");
stakingLogger.logDelegatorUnstaked(validatorId, msg.sender, _amount);
delete unbonds[msg.sender];
return _amount;
}
function slash(uint256 valPow, uint256 totalAmountToSlash) external onlyOwner returns (uint256) {
uint256 _withdrawPool = withdrawPool;
uint256 delegationAmount = activeAmount.add(_withdrawPool);
if (delegationAmount == 0) {
return 0;
}
// total amount to be slashed from delegation pool (active + inactive)
uint256 _amountToSlash = delegationAmount.mul(totalAmountToSlash).div(valPow.add(delegationAmount));
uint256 _amountToSlashWithdrawalPool = _withdrawPool.mul(_amountToSlash).div(delegationAmount);
// slash inactive pool
_reduceActiveStake(_amountToSlash.sub(_amountToSlashWithdrawalPool));
_reduceWithdrawPool(_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");
}
}
function getActiveAmount() external view returns(uint256) {
return activeAmount;
}
function unlockContract() external onlyOwner returns (uint256) {
unlock();
return activeAmount;
}
function lockContract() external onlyOwner returns (uint256) {
lock();
return activeAmount;
}
}
// 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/staking/stakeManager/StakeManagerStorage.sol
pragma solidity ^0.5.2;
contract StakeManagerStorage is GovernanceLockable, RootChainable {
IERC20 public token;
address public registry;
StakingInfo public logger;
StakingNFT public NFTContract;
ValidatorShareFactory public factory;
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;
struct Auction {
uint256 amount;
uint256 startEpoch;
address user;
bool acceptDelegation;
bytes signerPubkey;
}
struct State {
uint256 amount;
uint256 stakerCount;
}
struct StateChange {
int256 amount;
int256 stakerCount;
}
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;
// signer to Validator mapping
mapping(address => uint256) public signerToValidator;
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/StakeManager.sol
pragma solidity ^0.5.2;
contract StakeManager is IStakeManager, StakeManagerStorage, Initializable {
using SafeMath for uint256;
using ECVerify for bytes32;
using Merkle for bytes32;
using RLPReader for bytes;
using RLPReader for RLPReader.RLPItem;
uint256 private constant INCORRECT_VALIDATOR_ID = 2**256 - 1;
modifier onlyStaker(uint256 validatorId) {
_assertOnlyStaker(validatorId);
_;
}
function _assertOnlyStaker(uint256 validatorId) private view {
require(NFTContract.ownerOf(validatorId) == msg.sender);
}
constructor() public GovernanceLockable(address(0x0)) {}
function initialize(
address _registry,
address _rootchain,
address _token,
address _NFTContract,
address _stakingLogger,
address _validatorShareFactory,
address _governance,
address _owner
) external initializer {
governance = IGovernance(_governance);
registry = _registry;
rootChain = _rootchain;
token = IERC20(_token);
NFTContract = StakingNFT(_NFTContract);
logger = StakingInfo(_stakingLogger);
factory = 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 setDelegationEnabled(bool enabled) public onlyGovernance {
delegationEnabled = enabled;
}
// TopUp heimdall fee
function topUpForFee(address user, uint256 heimdallFee) public onlyWhenUnlocked {
_transferAndTopUp(user, heimdallFee, 0);
}
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 _transferAndTopUp(
address user,
uint256 fee,
uint256 additionalAmount
) private {
require(fee >= minHeimdallFee, "Not enough heimdall fee");
require(token.transferFrom(msg.sender, address(this), fee.add(additionalAmount)), "Fee transfer failed");
totalHeimdallFee = totalHeimdallFee.add(fee);
logger.logTopUpFee(user, fee);
}
function _claimFee(address user, uint256 amount) private {
totalHeimdallFee = totalHeimdallFee.sub(amount);
logger.logClaimFee(user, amount);
}
function claimFee(
uint256 accumFeeAmount,
uint256 index,
bytes memory proof
) public {
//Ignoring other params becuase 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;
require(token.transfer(msg.sender, withdrawAmount));
}
function stake(
uint256 amount,
uint256 heimdallFee,
bool acceptDelegation,
bytes calldata signerPubkey
) external {
stakeFor(msg.sender, amount, heimdallFee, acceptDelegation, signerPubkey);
}
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 {
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;
address _contract = validators[validatorId].contractAddress;
if (_contract != address(0x0)) {
perceivedStake = perceivedStake.add(IValidatorShare(_contract).getActiveAmount());
}
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 amount 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 */
) external onlyWhenUnlocked {
Auction storage auction = validatorAuction[validatorId];
address auctionUser = auction.user;
require(
msg.sender == auctionUser || getValidatorId(msg.sender) == validatorId,
"Only bidder or validator 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;
address contractAddr = validators[validatorId].contractAddress;
if (contractAddr != address(0x0)) {
perceivedStake = perceivedStake.add(IValidatorShare(contractAddr).getActiveAmount());
}
// 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 {
// dethrone
_transferAndTopUp(auctionUser, heimdallFee, 0);
_unstake(validatorId, _currentEpoch);
uint256 newValidatorId = _stakeFor(
auctionUser,
auctionAmount,
auction.acceptDelegation,
auction.signerPubkey
);
logger.logConfirmAuction(newValidatorId, validatorId, auctionAmount);
}
uint256 startEpoch = auction.startEpoch;
delete validatorAuction[validatorId];
validatorAuction[validatorId].startEpoch = startEpoch;
}
function unstake(uint256 validatorId) external onlyStaker(validatorId) {
require(validatorAuction[validatorId].amount == 0, "Wait for auction completion");
require(
validators[validatorId].activationEpoch > 0 &&
validators[validatorId].deactivationEpoch == 0 &&
(validators[validatorId].status == Status.Active || validators[validatorId].status == Status.Locked)
);
uint256 exitEpoch = currentEpoch.add(1); // notice period
_unstake(validatorId, exitEpoch);
}
// Housekeeping function. @todo remove later
function forceUnstake(uint256 validatorId) external onlyGovernance {
_unstake(validatorId, currentEpoch);
}
function setCurrentEpoch(uint256 _currentEpoch) external onlyGovernance {
currentEpoch = _currentEpoch;
}
function transferFunds(
uint256 validatorId,
uint256 amount,
address delegator
) external returns (bool) {
require(
validators[validatorId].contractAddress == msg.sender ||
Registry(registry).getSlashingManagerAddress() == msg.sender,
"Invalid contract address"
);
return token.transfer(delegator, amount);
}
function delegationDeposit(
uint256 validatorId,
uint256 amount,
address delegator
) external returns (bool) {
require(validators[validatorId].contractAddress == msg.sender, "Invalid contract address");
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, "Validator set Threshold exceeded!");
require(amount > minDeposit, "min deposit limit failed!");
_transferAndTopUp(user, 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;
NFTContract.burn(validatorId);
signerToValidator[validators[validatorId].signer] = INCORRECT_VALIDATOR_ID;
validators[validatorId].status = Status.Unstaked;
require(token.transfer(msg.sender, amount), "Transfer stake failed");
logger.logUnstaked(msg.sender, validatorId, amount, newTotalStaked);
}
// slashing and jail interface
function restake(
uint256 validatorId,
uint256 amount,
bool stakeRewards
) public onlyWhenUnlocked onlyStaker(validatorId) {
require(validators[validatorId].deactivationEpoch == 0, "No use of restaking");
if (amount > 0) {
require(token.transferFrom(msg.sender, address(this), amount), "Transfer stake failed");
}
if (stakeRewards) {
amount = amount.add(validators[validatorId].reward);
address contractAddr = validators[validatorId].contractAddress;
if (contractAddr != address(0x0)) {
amount = amount.add(IValidatorShare(contractAddr).withdrawRewardsValidator());
}
validators[validatorId].reward = 0;
}
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 _liquidateRewards(uint256 validatorId, address validatorUser, uint256 reward) private {
totalRewardsLiquidated = totalRewardsLiquidated.add(reward);
validators[validatorId].reward = 0;
require(token.transfer(validatorUser, reward), "Insufficent rewards");
logger.logClaimRewards(validatorId, reward, totalRewardsLiquidated);
}
function withdrawRewards(uint256 validatorId) public onlyStaker(validatorId) {
uint256 reward = validators[validatorId].reward;
address contractAddr = validators[validatorId].contractAddress;
if (contractAddr != address(0x0)) {
reward = reward.add(IValidatorShare(contractAddr).withdrawRewardsValidator());
}
_liquidateRewards(validatorId, msg.sender, reward);
}
function migrateDelegation(uint256 fromValidatorId, uint256 toValidatorId, uint256 amount) public {
require(fromValidatorId < 8 && toValidatorId > 7, "Invalid migration");
IValidatorShare(validators[fromValidatorId].contractAddress).migrateOut(msg.sender, amount);
IValidatorShare(validators[toValidatorId].contractAddress).migrateIn(msg.sender, amount);
}
function getValidatorId(address user) public view returns (uint256) {
return NFTContract.tokenOfOwnerByIndex(user, 0);
}
// set staking Token
function setToken(address _token) public onlyGovernance {
require(_token != address(0x0));
token = IERC20(_token);
}
// 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, "Blocks interval must be non-zero");
checkPointBlockInterval = _blocks;
}
// Change reward for each checkpoint
function updateCheckpointReward(uint256 newReward) public onlyGovernance {
require(newReward > 0);
logger.logRewardUpdate(newReward, CHECKPOINT_REWARD);
CHECKPOINT_REWARD = newReward;
}
// Change delegation contract for a validator
// @note: Users must exit before this update or all funds may get lost
function updateContractAddress(uint256 validatorId, address newContractAddress) public onlyGovernance {
require(IValidatorShare(newContractAddress).owner() == address(this), "Owner of contract must be stakeManager");
validators[validatorId].contractAddress = newContractAddress;
}
function updateValidatorState(uint256 validatorId, int256 amount) public {
if (amount > 0) {
// deposit during shares purchase
require(delegationEnabled, "Delegation is disabled");
}
require(validators[validatorId].contractAddress == msg.sender, "Invalid contract address");
updateTimeline(amount, 0, 0);
}
function updateDynastyValue(uint256 newDynasty) public onlyGovernance {
require(newDynasty > 0);
logger.logDynastyValueChange(newDynasty, dynasty);
dynasty = newDynasty;
WITHDRAWAL_DELAY = newDynasty;
auctionPeriod = newDynasty.div(4);
// set cooldown period
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 <= 100, "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 updateSigner(uint256 validatorId, bytes memory signerPubkey) public onlyStaker(validatorId) {
address signer = pubToAddress(signerPubkey);
require(signer != address(0x0) && signerToValidator[signer] == 0, "Invalid signer");
uint256 _currentEpoch = currentEpoch;
require(
_currentEpoch >= latestSignerUpdateEpoch[validatorId].add(signerUpdateLimit),
"Invalid checkpoint number!"
);
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;
// reset update time to current time
latestSignerUpdateEpoch[validatorId] = _currentEpoch;
}
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) {
uint256 activationEpoch = validators[validatorId].activationEpoch;
uint256 deactivationEpoch = validators[validatorId].deactivationEpoch;
uint256 amount = validators[validatorId].amount;
Status status = validators[validatorId].status;
uint256 _currentEpoch = currentEpoch;
return (amount > 0 &&
(activationEpoch != 0 && activationEpoch <= _currentEpoch) &&
(deactivationEpoch == 0 || deactivationEpoch > _currentEpoch) &&
status == Status.Active);
}
function checkSignatures(
uint256 blockInterval,
bytes32 voteHash,
bytes32 stateRoot,
address proposer,
bytes memory sigs
) public onlyRootChain returns (uint256) {
// checkpoint rewards are based on BlockInterval multiplied on `CHECKPOINT_REWARD`
// for bigger checkpoints reward is capped at `CHECKPOINT_REWARD`
// 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 reward = blockInterval.mul(CHECKPOINT_REWARD).div(checkPointBlockInterval);
reward = Math.min(CHECKPOINT_REWARD, reward);
uint256 _proposerBonus = reward.mul(proposerBonus).div(100);
Validator storage _proposer = validators[signerToValidator[proposer]];
if (_proposer.contractAddress != address(0x0)) {
IValidatorShare(_proposer.contractAddress).addProposerBonus(_proposerBonus, _proposer.amount);
} else {
_proposer.reward = _proposer.reward.add(_proposerBonus);
}
reward = reward.sub(_proposerBonus);
uint256 stakePower = currentValidatorSetTotalStake();
// update stateMerkleTree root for accounts balance on heimdall chain
accountStateRoot = stateRoot;
_finalizeCommit();
return checkSignature(stakePower, reward, voteHash, sigs);
}
function checkSignature(
uint256 checkpointStakePower,
uint256 reward,
bytes32 voteHash,
bytes memory sigs
) internal returns (uint256) {
// total voting power
uint256 totalStakePower;
address lastAdd; // cannot have address(0x0) as an owner
for (uint64 i = 0; i < sigs.length; i += 65) {
address signer = voteHash.ecrecovery(BytesLib.slice(sigs, i, 65));
uint256 validatorId = signerToValidator[signer];
// check if signer is staker and not proposer
if (signer == lastAdd) {
break;
} else if (isValidator(validatorId) && signer > lastAdd) {
lastAdd = signer;
Validator storage validator = validators[validatorId];
uint256 valPow;
// add delegation power
address contractAddr = validator.contractAddress;
if (contractAddr != address(0x0)) {
valPow = IValidatorShare(contractAddr).updateRewards(
reward,
checkpointStakePower,
validatorStake(validatorId)
);
} else {
valPow = validator.amount;
validator.reward = validator.reward.add(valPow.mul(reward).div(checkpointStakePower));
}
totalStakePower = totalStakePower.add(valPow);
}
}
reward = CHECKPOINT_REWARD.mul(totalStakePower).div(currentValidatorSetTotalStake());
totalRewards = totalRewards.add(reward);
require(totalStakePower >= currentValidatorSetTotalStake().mul(2).div(3).add(1), "2/3+1 non-majority!");
return reward;
}
function slash(bytes memory _slashingInfoList) public returns (uint256) {
require(Registry(registry).getSlashingManagerAddress() == msg.sender, "Sender must be slashing manager!");
RLPReader.RLPItem[] memory slashingInfoList = _slashingInfoList.toRlpItem().toList();
int256 valJailed = 0;
uint256 jailedAmount = 0;
uint256 totalAmount;
for (uint256 i = 0; i < slashingInfoList.length; i++) {
RLPReader.RLPItem[] memory slashData = slashingInfoList[i].toList();
uint256 validatorId = slashData[0].toUint();
uint256 _amount = slashData[1].toUint();
totalAmount = totalAmount.add(_amount);
if (validators[validatorId].contractAddress != address(0x0)) {
uint256 delSlashedAmount = IValidatorShare(validators[validatorId].contractAddress).slash(
validators[validatorId].amount,
_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, "Validator is not jailed");
require(validators[validatorId].deactivationEpoch == 0, "Validator already unstaking");
uint256 _currentEpoch = currentEpoch;
require(validators[validatorId].jailTime <= _currentEpoch, "Incomplete jail period");
uint256 amount = validators[validatorId].amount;
require(amount >= minDeposit);
uint256 delegationAmount = 0;
if (validators[validatorId].contractAddress != address(0x0)) {
delegationAmount = IValidatorShare(validators[validatorId].contractAddress).unlockContract();
}
// undo timline so that validator is normal validator
updateTimeline(int256(amount.add(delegationAmount)), 1, 0);
validators[validatorId].status = Status.Active;
logger.logUnjailed(validatorId, validators[validatorId].signer);
}
function _jail(uint256 validatorId, uint256 jailCheckpoints) internal returns (uint256) {
uint256 delegationAmount = 0;
if (validators[validatorId].contractAddress != address(0x0)) {
delegationAmount = IValidatorShare(validators[validatorId].contractAddress).lockContract();
}
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(delegationAmount);
}
function _stakeFor(
address user,
uint256 amount,
bool acceptDelegation,
bytes memory signerPubkey
) internal returns (uint256) {
address signer = pubToAddress(signerPubkey);
require(signer != address(0x0) && signerToValidator[signer] == 0, "Invalid signer");
uint256 _currentEpoch = currentEpoch;
uint256 validatorId = NFTCounter;
StakingInfo _logger = logger;
uint256 newTotalStaked = totalStaked.add(amount);
totalStaked = newTotalStaked;
validators[validatorId] = Validator({
reward: 0,
amount: amount,
activationEpoch: _currentEpoch,
deactivationEpoch: 0,
jailTime: 0,
signer: signer,
contractAddress: acceptDelegation ? factory.create(validatorId, address(_logger), registry) : address(0x0),
status: Status.Active
});
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);
return validatorId;
}
function _unstake(uint256 validatorId, uint256 exitEpoch) internal {
uint256 amount = validators[validatorId].amount;
address validator = ownerOf(validatorId);
validators[validatorId].deactivationEpoch = exitEpoch;
// unbond all delegators in future
int256 delegationAmount = 0;
uint256 rewards = validators[validatorId].reward;
address contractAddr = validators[validatorId].contractAddress;
if (contractAddr != address(0x0)) {
IValidatorShare validatorShare = IValidatorShare(contractAddr);
rewards = rewards.add(validatorShare.withdrawRewardsValidator());
delegationAmount = int256(validatorShare.lockContract());
}
_liquidateRewards(validatorId, validator, rewards);
// update future
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 updateTimeline(
int256 amount,
int256 stakerCount,
uint256 targetEpoch
) private {
if (targetEpoch == 0) {
// update totalstake 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 pubToAddress(bytes memory pub) private pure returns (address) {
require(pub.length == 64, "Invalid pubkey");
return address(uint160(uint256(keccak256(pub))));
}
function reinitialize(
address _NFTContract,
address _stakingLogger,
address _validatorShareFactory
) external onlyGovernance {
NFTContract = StakingNFT(_NFTContract);
logger = StakingInfo(_stakingLogger);
factory = ValidatorShareFactory(_validatorShareFactory);
}
function updateValidatorDelegation(bool delegation) external {
uint256 validatorId = signerToValidator[msg.sender];
require(isValidator(validatorId), "not a validator");
address contractAddr = validators[validatorId].contractAddress;
require(contractAddr != address(0x0), "delegation not enabled");
IValidatorShare(contractAddr).updateDelegation(delegation);
}
}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":"bytes","name":"sigs","type":"bytes"}],"name":"checkSignatures","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","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"},{"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":[],"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":"factory","outputs":[{"internalType":"contract ValidatorShareFactory","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":[{"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"}],"name":"initialize","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":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":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":"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"}],"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":"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":"setToken","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":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":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"heimdallFee","type":"uint256"},{"internalType":"bool","name":"acceptDelegation","type":"bool"},{"internalType":"bytes","name":"signerPubkey","type":"bytes"}],"name":"stake","outputs":[],"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":"validatorId","type":"uint256"},{"internalType":"address","name":"newContractAddress","type":"address"}],"name":"updateContractAddress","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":"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":"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"}],"payable":false,"stateMutability":"view","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
60806040526023805460ff1916905534801561001a57600080fd5b5060008054610100600160a81b0319168155600180546001600160a01b0319163317908190556040516001600160a01b039190911691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3615dc980620000866000396000f3fe608060405234801561001057600080fd5b50600436106104b75760003560e01c80637b10399911610278578063bc8756a91161015c578063eceec1d3116100ce578063f4547a4d11610092578063f4547a4d14611124578063f771fc8714611150578063f83d08ba1461116d578063fb1ef52c14611175578063fba58f341461119e578063fc0c546a146111a6576104b7565b8063eceec1d31461100f578063f24ccbfe1461102c578063f28699fa14611034578063f2fde38b14611053578063f41a964214611079576104b7565b8063d6de07d011610120578063d6de07d014610f6b578063d7f5549d14610f8a578063d86d53e714610fa7578063e59ee0c614610fc4578063e6692f4914610fcc578063e8afa8e814610fe9576104b7565b8063bc8756a914610f04578063c45a015514610f36578063cbf383d514610f3e578063cd6b838814610f5b578063cf30901214610f63576104b7565b8063987ab9db116101f5578063a440ab1e116101b9578063a440ab1e14610e29578063a476907114610e46578063a685487714610e4e578063a69df4b514610ed1578063a7ab696114610ed9578063b1d23f0214610ee1576104b7565b8063987ab9db14610db657806399d18f6f14610dbe5780639a8a624314610de15780639b33f43414610de95780639ff1150014610e06576104b7565b80638da5cb5b1161023c5780638da5cb5b14610d645780638f32d59b14610d6c578063900cf0cf14610d745780639146014914610d7c5780639342c8f414610d99576104b7565b80637b10399914610ce55780637d66975214610ced5780637f952d9514610cf5578063817b1cd214610cfd5780638a29e2de14610d05576104b7565b806341b3d1851161039f5780635e47655f1161031c5780636901b253116102e05780636901b25314610c6d5780637060054d14610c9f578063715018a614610ca75780637667180814610caf57806377939d1014610cb757806378f84a4414610cbf576104b7565b80635e47655f14610a985780636352211e14610b3c5780636365679814610b595780636400e38514610b8557806368cb812a14610bbd576104b7565b80635325e144116103635780635325e1441461099c57806354b8c60114610a635780635508d8e114610a6b57806356342d8c14610a735780635aa6e67514610a90576104b7565b806341b3d185146108975780634b341aed1461089f5780634e3c83f1146108c55780634fd101d7146108cd5780634fdd20f1146108d5576104b7565b806317c2b9101161043857806328cc4e41116103fc57806328cc4e41146107675780632e17de781461079257806331c2273b146107af57806334274586146107d357806335aa2e44146107db5780633862da0b14610871576104b7565b806317c2b910146106d35780631dd6b9b1146106db57806325316411146106f857806325726df2146107005780632649263a14610736576104b7565b80630ebb172a1161047f5780630ebb172a14610645578063144fa6d71461064d57806316827b1b14610673578063174e683214610690578063178c2c83146106b6576104b7565b8063028c4c67146104bc578063066647a01461054157806306cfb104146106185780630cccfc58146106355780630e15561a1461063d575b600080fd5b61053f600480360360808110156104d257600080fd5b813591602081013591604082013515159190810190608081016060820135600160201b81111561050157600080fd5b82018360208201111561051357600080fd5b803590602001918460018302840111600160201b8311171561053457600080fd5b5090925090506111ae565b005b610606600480360360a081101561055757600080fd5b8135916020810135916040820135916001600160a01b036060820135169181019060a081016080820135600160201b81111561059257600080fd5b8201836020820111156105a457600080fd5b803590602001918460018302840111600160201b831117156105c557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506111f8945050505050565b60408051918252519081900360200190f35b61053f6004803603602081101561062e57600080fd5b5035611371565b6106066113c4565b6106066113ca565b6106066113d0565b61053f6004803603602081101561066357600080fd5b50356001600160a01b03166113d6565b61053f6004803603602081101561068957600080fd5b5035611459565b610606600480360360208110156106a657600080fd5b50356001600160a01b031661152b565b61053f600480360360208110156106cc57600080fd5b50356115b5565b610606611872565b61053f600480360360208110156106f157600080fd5b5035611878565b6106066118cb565b61071d6004803603602081101561071657600080fd5b50356118d1565b6040805192835260208301919091528051918290030190f35b6107536004803603602081101561074c57600080fd5b50356118ea565b604080519115158252519081900360200190f35b61053f6004803603606081101561077d57600080fd5b5080359060208101359060400135151561196b565b61053f600480360360208110156107a857600080fd5b5035611cac565b6107b7611dd8565b604080516001600160a01b039092168252519081900360200190f35b610606611de7565b6107f8600480360360208110156107f157600080fd5b5035611ded565b60405180898152602001888152602001878152602001868152602001858152602001846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b0316815260200182600381111561085657fe5b60ff1681526020019850505050505050505060405180910390f35b6106066004803603602081101561088757600080fd5b50356001600160a01b0316611e43565b610606611e55565b610606600480360360208110156108b557600080fd5b50356001600160a01b0316611e5b565b610606611f92565b610606611f98565b61053f600480360360a08110156108eb57600080fd5b6001600160a01b0382351691602081013591604082013591606081013515159181019060a081016080820135600160201b81111561092857600080fd5b82018360208201111561093a57600080fd5b803590602001918460018302840111600160201b8311171561095b57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611f9e945050505050565b6109b9600480360360208110156109b257600080fd5b5035612062565b60405180868152602001858152602001846001600160a01b03166001600160a01b031681526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610a24578181015183820152602001610a0c565b50505050905090810190601f168015610a515780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b610753612128565b610606612131565b6107b760048036036020811015610a8957600080fd5b5035612137565b6107b7612155565b61060660048036036020811015610aae57600080fd5b810190602081018135600160201b811115610ac857600080fd5b820183602082011115610ada57600080fd5b803590602001918460018302840111600160201b83111715610afb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612169945050505050565b6107b760048036036020811015610b5257600080fd5b503561244e565b61053f60048036036040811015610b6f57600080fd5b506001600160a01b03813516906020013561249a565b61053f60048036036060811015610b9b57600080fd5b506001600160a01b0381358116916020810135821691604090910135166124b2565b61053f60048036036060811015610bd357600080fd5b813591602081013591810190606081016040820135600160201b811115610bf957600080fd5b820183602082011115610c0b57600080fd5b803590602001918460018302840111600160201b83111715610c2c57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061253f945050505050565b61075360048036036060811015610c8357600080fd5b50803590602081013590604001356001600160a01b0316612776565b61060661286f565b61053f612875565b6106066128d0565b6106066128d6565b61060660048036036020811015610cd557600080fd5b50356001600160a01b03166128dc565b6107b76128ee565b6106066128fd565b610606612903565b61060661290a565b61053f6004803603610100811015610d1c57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c082013581169160e0013516612910565b6107b7612a59565b610753612a68565b610606612a79565b61053f60048036036020811015610d9257600080fd5b5035612a7f565b61053f60048036036020811015610daf57600080fd5b5035612adc565b6107b7612b93565b61053f60048036036040811015610dd457600080fd5b5080359060200135612ba2565b610606613098565b61053f60048036036020811015610dff57600080fd5b503561309e565b61053f60048036036040811015610e1c57600080fd5b50803590602001356131a0565b61053f60048036036020811015610e3f57600080fd5b503561326e565b610606613316565b61053f60048036036080811015610e6457600080fd5b813591602081013591604082013515159190810190608081016060820135600160201b811115610e9357600080fd5b820183602082011115610ea557600080fd5b803590602001918460018302840111600160201b83111715610ec657600080fd5b50909250905061331c565b61053f61389d565b6106066138f5565b61053f60048036036040811015610ef757600080fd5b50803590602001356138fb565b61075360048036036060811015610f1a57600080fd5b50803590602081013590604001356001600160a01b0316613954565b6107b7613a95565b61053f60048036036020811015610f5457600080fd5b5035613aa4565b610606613b76565b610753613b7c565b61053f60048036036020811015610f8157600080fd5b50351515613b85565b61060660048036036020811015610fa057600080fd5b5035613cad565b61053f60048036036020811015610fbd57600080fd5b5035613cbf565b61071d613f30565b61053f60048036036020811015610fe257600080fd5b5035613f39565b61053f60048036036020811015610fff57600080fd5b50356001600160a01b031661403b565b6106066004803603602081101561102557600080fd5b50356140bb565b6107b76140cd565b61053f6004803603602081101561104a57600080fd5b503515156140dc565b61053f6004803603602081101561106957600080fd5b50356001600160a01b031661413d565b61053f6004803603604081101561108f57600080fd5b81359190810190604081016020820135600160201b8111156110b057600080fd5b8201836020820111156110c257600080fd5b803590602001918460018302840111600160201b831117156110e357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550614157945050505050565b61053f6004803603604081101561113a57600080fd5b50803590602001356001600160a01b03166143b0565b61053f6004803603602081101561116657600080fd5b50356144e3565b61053f614544565b61053f6004803603606081101561118b57600080fd5b508035906020810135906040013561459a565b6106066146c1565b6107b76146c7565b6111f13386868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f9e92505050565b5050505050565b6002546000906001600160a01b0316331461121257600080fd5b600061123b600e5461122f600b548a6146d690919063ffffffff16565b9063ffffffff61470616565b9050611249600b5482614728565b90506000611267606461122f601654856146d690919063ffffffff16565b6001600160a01b038087166000908152601b60209081526040808320548352601a909152902060068101549293509116156113115760068101548154604080516301a6632160e31b8152600481018690526024810192909252516001600160a01b0390921691630d3319089160448082019260009290919082900301818387803b1580156112f457600080fd5b505af1158015611308573d6000803e3d6000fd5b5050505061132c565b6001810154611326908363ffffffff61473e16565b60018201555b61133c838363ffffffff61475016565b92506000611348613316565b60178990559050611357614765565b61136381858b896147da565b9a9950505050505050505050565b60005461010090046001600160a01b031633146113bf5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b600f55565b60155481565b60135481565b60085481565b60005461010090046001600160a01b031633146114245760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b6001600160a01b03811661143757600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60005461010090046001600160a01b031633146114a75760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b600081116114b457600080fd5b60055460105460408051630f1980a560e41b8152600481018590526024810192909252516001600160a01b039092169163f1980a509160448082019260009290919082900301818387803b15801561150b57600080fd5b505af115801561151f573d6000803e3d6000fd5b50505060109190915550565b60065460408051632f745c5960e01b81526001600160a01b038481166004830152600060248301819052925192931691632f745c5991604480820192602092909190829003018186803b15801561158157600080fd5b505afa158015611595573d6000803e3d6000fd5b505050506040513d60208110156115ab57600080fd5b505190505b919050565b806115bf81614b16565b60026000838152601a6020526040902060060154600160a01b900460ff1660038111156115e857fe5b1461163a576040805162461bcd60e51b815260206004820152601760248201527f56616c696461746f72206973206e6f74206a61696c6564000000000000000000604482015290519081900360640190fd5b6000828152601a60205260409020600301541561169e576040805162461bcd60e51b815260206004820152601b60248201527f56616c696461746f7220616c726561647920756e7374616b696e670000000000604482015290519081900360640190fd5b6009546000838152601a6020526040902060040154811015611700576040805162461bcd60e51b8152602060048201526016602482015275125b98dbdb5c1b195d19481a985a5b081c195c9a5bd960521b604482015290519081900360640190fd5b6000838152601a6020526040902054600c5481101561171e57600080fd5b6000848152601a60205260408120600601546001600160a01b0316156117c2576000858152601a602090815260408083206006015481516322f0f2f960e01b815291516001600160a01b03909116936322f0f2f993600480850194919392918390030190829087803b15801561179357600080fd5b505af11580156117a7573d6000803e3d6000fd5b505050506040513d60208110156117bd57600080fd5b505190505b6117de6117d5838363ffffffff61473e16565b60016000614ba0565b6000858152601a602052604080822060068101805460ff60a01b1916600160a01b17905560058054910154825163f92ec5af60e01b8152600481018a90526001600160a01b039182166024820152925191169263f92ec5af926044808201939182900301818387803b15801561185357600080fd5b505af1158015611867573d6000803e3d6000fd5b505050505050505050565b60175481565b60005461010090046001600160a01b031633146118c65760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b600955565b600e5481565b601e602052600090815260409020805460019091015482565b6000818152601a6020526040812060028101546003820154825460069093015460095492939192600160a01b90910460ff16908215801590611936575084158015906119365750808511155b8015611949575083158061194957508084115b80156119605750600182600381111561195e57fe5b145b979650505050505050565b611973614c5c565b8261197d81614b16565b6000848152601a6020526040902060030154156119d7576040805162461bcd60e51b81526020600482015260136024820152724e6f20757365206f662072657374616b696e6760681b604482015290519081900360640190fd5b8215611aac57600354604080516323b872dd60e01b81523360048201523060248201526044810186905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b158015611a3757600080fd5b505af1158015611a4b573d6000803e3d6000fd5b505050506040513d6020811015611a6157600080fd5b5051611aac576040805162461bcd60e51b8152602060048201526015602482015274151c985b9cd9995c881cdd185ad94819985a5b1959605a1b604482015290519081900360640190fd5b8115611b87576000848152601a6020526040902060010154611ad590849063ffffffff61473e16565b6000858152601a60205260409020600601549093506001600160a01b03168015611b7357611b70816001600160a01b03166332ba2e536040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b3757600080fd5b505af1158015611b4b573d6000803e3d6000fd5b505050506040513d6020811015611b6157600080fd5b5051859063ffffffff61473e16565b93505b506000848152601a60205260408120600101555b601154600090611b9d908563ffffffff61473e16565b60118190556000868152601a6020526040902054909150611bc4908563ffffffff61473e16565b6000868152601a6020526040812091909155611be290859080614ba0565b6005546040805163532e19a960e01b81526004810188905290516001600160a01b039092169163532e19a99160248082019260009290919082900301818387803b158015611c2f57600080fd5b505af1158015611c43573d6000803e3d6000fd5b50506005546000888152601a6020526040808220548151631585a9f360e21b8152600481018c905260248101919091526044810187905290516001600160a01b039093169450635616a7cc93506064808201939182900301818387803b15801561185357600080fd5b80611cb681614b16565b600082815260208052604090205415611d16576040805162461bcd60e51b815260206004820152601b60248201527f5761697420666f722061756374696f6e20636f6d706c6574696f6e0000000000604482015290519081900360640190fd5b6000828152601a602052604090206002015415801590611d4557506000828152601a6020526040902060030154155b8015611da7575060016000838152601a6020526040902060060154600160a01b900460ff166003811115611d7557fe5b1480611da7575060026000838152601a6020526040902060060154600160a01b900460ff166003811115611da557fe5b145b611db057600080fd5b600954600090611dc790600163ffffffff61473e16565b9050611dd38382614c9d565b505050565b6006546001600160a01b031681565b60165481565b601a602052600090815260409020805460018201546002830154600384015460048501546005860154600690960154949593949293919290916001600160a01b039081169190811690600160a01b900460ff1688565b601b6020526000908152604090205481565b600c5481565b60006001600160a01b0382161580611ee95750600654604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b158015611ebb57600080fd5b505afa158015611ecf573d6000803e3d6000fd5b505050506040513d6020811015611ee557600080fd5b5051155b15611ef6575060006115b0565b60065460408051632f745c5960e01b81526001600160a01b0385811660048301526000602483018190529251601a949190911691632f745c59916044808301926020929190829003018186803b158015611f4f57600080fd5b505afa158015611f63573d6000803e3d6000fd5b505050506040513d6020811015611f7957600080fd5b5051815260208101919091526040016000205492915050565b600f5481565b60105481565b611fa6614c5c565b601054611fb1612903565b10611fed5760405162461bcd60e51b8152600401808060200182810382526021815260200180615d046021913960400191505060405180910390fd5b600c548411612043576040805162461bcd60e51b815260206004820152601960248201527f6d696e206465706f736974206c696d6974206661696c65642100000000000000604482015290519081900360640190fd5b61204e858486614e67565b61205a85858484615027565b505050505050565b60208080526000918252604091829020805460018083015460028085015460038601805489516101009682161596909602600019011692909204601f8101889004880285018801909852878452939691956001600160a01b03851695600160a01b90950460ff169493929083018282801561211e5780601f106120f35761010080835404028352916020019161211e565b820191906000526020600020905b81548152906001019060200180831161210157829003601f168201915b5050505050905085565b60195460ff1681565b60125481565b6000908152601a60205260409020600601546001600160a01b031690565b60005461010090046001600160a01b031681565b6004805460408051631ab0168360e31b8152905160009333936001600160a01b03169263d580b4189281830192602092829003018186803b1580156121ad57600080fd5b505afa1580156121c1573d6000803e3d6000fd5b505050506040513d60208110156121d757600080fd5b50516001600160a01b031614612234576040805162461bcd60e51b815260206004820181905260248201527f53656e646572206d75737420626520736c617368696e67206d616e6167657221604482015290519081900360640190fd5b60606122476122428461543d565b615462565b905060008080805b845181101561242357606061227686838151811061226957fe5b6020026020010151615462565b905060006122978260008151811061228a57fe5b6020026020010151615533565b905060006122ab8360018151811061228a57fe5b90506122bd858263ffffffff61473e16565b6000838152601a60205260409020600601549095506001600160a01b031615612385576000828152601a602090815260408083206006810154905482516314454c8560e31b815260048101919091526024810186905291516001600160a01b039091169263a22a6428926044808201939182900301818787803b15801561234357600080fd5b505af1158015612357573d6000803e3d6000fd5b505050506040513d602081101561236d57600080fd5b50519050612381828263ffffffff61475016565b9150505b6000828152601a60205260408120546123a4908363ffffffff61475016565b6000848152601a602052604090208190559050806123cd576123c883600954614c9d565b612413565b6123ea846002815181106123dd57fe5b6020026020010151615593565b156124135761240a6123fd8460016155c7565b889063ffffffff61473e16565b60019098019796505b50506001909201915061224f9050565b50612445612437828463ffffffff61473e16565b600003846000036000614ba0565b95945050505050565b600654604080516331a9108f60e11b81526004810184905290516000926001600160a01b031691636352211e916024808301926020929190829003018186803b15801561158157600080fd5b6124a2614c5c565b6124ae82826000614e67565b5050565b60005461010090046001600160a01b031633146125005760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b600680546001600160a01b039485166001600160a01b031991821617909155600580549385169382169390931790925560078054919093169116179055565b60408051336020808301919091528183018690528251808303840181526060830193849052805190820120601754631b23d15760e21b909452606483018181526084840187905260a48401859052608060c48501908152865160e486015286517329d2706cdb97783a652314863668ed5cab971db296636c8f455c9694958a9591948a9490939092610104019185019080838360005b838110156125ed5781810151838201526020016125d5565b50505050905090810190601f16801561261a5780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038186803b15801561263a57600080fd5b505af415801561264e573d6000803e3d6000fd5b505050506040513d602081101561266457600080fd5b50516126a9576040805162461bcd60e51b815260206004820152600f60248201526e2bb937b7339030b1b190383937b7b360891b604482015290519081900360640190fd5b336000908152601f60205260408120546126ca90859063ffffffff61475016565b90506126d6338261573c565b336000818152601f60209081526040808320889055600354815163a9059cbb60e01b815260048101959095526024850186905290516001600160a01b039091169363a9059cbb9360448083019493928390030190829087803b15801561273b57600080fd5b505af115801561274f573d6000803e3d6000fd5b505050506040513d602081101561276557600080fd5b505161277057600080fd5b50505050565b6000838152601a60205260408120600601546001600160a01b031633146127df576040805162461bcd60e51b8152602060048201526018602482015277496e76616c696420636f6e7472616374206164647265737360401b604482015290519081900360640190fd5b600354604080516323b872dd60e01b81526001600160a01b03858116600483015230602483015260448201879052915191909216916323b872dd9160648083019260209291908290030181600087803b15801561283b57600080fd5b505af115801561284f573d6000803e3d6000fd5b505050506040513d602081101561286557600080fd5b5051949350505050565b600a5481565b61287d612a68565b61288657600080fd5b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b60095481565b60185481565b601f6020526000908152604090205481565b6004546001600160a01b031681565b600b5481565b601d545b90565b60115481565b60235460ff1615612959576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b60238054600160ff1990911617905560008054610100600160a81b0319166101006001600160a01b038581169190910291909117909155600480546001600160a01b03199081168b8416179091556002805482168a8416179055600380548216898416179055600680548216888416179055600580548216878416179055600780549091169185169190911790556129f0816157bb565b5050612000600855505060016009819055610376600a90815569044664c7bf6451f00000600b55670de0b6b3a7640000600c819055600d55610400600e556064600f55600760105560128290556108006015556016556019805460ff1916909117905550505050565b6001546001600160a01b031690565b6001546001600160a01b0316331490565b60095490565b60005461010090046001600160a01b03163314612acd5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b612ad981600954614c9d565b50565b80612ae681614b16565b6000828152601a6020526040902060018101546006909101546001600160a01b03168015612b8857612b85816001600160a01b03166332ba2e536040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612b4c57600080fd5b505af1158015612b60573d6000803e3d6000fd5b505050506040513d6020811015612b7657600080fd5b5051839063ffffffff61473e16565b91505b61277084338461582a565b6002546001600160a01b031681565b612baa614c5c565b6000828152602080526040902060028101546001600160a01b031633811480612bda575083612bd83361152b565b145b612c155760405162461bcd60e51b8152600401808060200182810382526024815260200180615d256024913960400191505060405180910390fd5b600954601554600a54612c2f90829063ffffffff61473e16565b6001850154612c4590849063ffffffff61475016565b81612c4c57fe5b061015612ca0576040805162461bcd60e51b815260206004820181905260248201527f4e6f7420616c6c6f776564206265666f72652061756374696f6e506572696f64604482015290519081900360640190fd5b60028301546001600160a01b0316612cf1576040805162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b21030bab1ba34b7b760891b604482015290519081900360640190fd5b6000858152601a6020526040902080548454600690920154909182916001600160a01b03168015612d9457612d91816001600160a01b031663a446c2db6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d5857600080fd5b505afa158015612d6c573d6000803e3d6000fd5b505050506040513d6020811015612d8257600080fd5b5051849063ffffffff61473e16565b92505b818310158015612db357506000898152601a6020526040902060030154155b15612efe576003546040805163a9059cbb60e01b81526001600160a01b038981166004830152602482018690529151919092169163a9059cbb9160448083019260209291908290030181600087803b158015612e0e57600080fd5b505af1158015612e22573d6000803e3d6000fd5b505050506040513d6020811015612e3857600080fd5b5051612e7f576040805162461bcd60e51b8152602060048201526011602482015270109a59081c995d1d5c9b8819985a5b1959607a1b604482015290519081900360640190fd5b600187018590556005546040805163e12ab1af60e01b8152600481018c9052602481018c90526044810187905290516001600160a01b039092169163e12ab1af9160648082019260009290919082900301818387803b158015612ee157600080fd5b505af1158015612ef5573d6000803e3d6000fd5b50505050613039565b612f0a86896000614e67565b612f148986614c9d565b6002878101546003890180546040805160206101006001851615026000190190931695909504601f8101839004830286018301909152808552600094612fc1948c948994600160a01b90920460ff16939091830182828015612fb75780601f10612f8c57610100808354040283529160200191612fb7565b820191906000526020600020905b815481529060010190602001808311612f9a57829003601f168201915b5050505050615027565b6005546040805163e12ab1af60e01b815260048101849052602481018e90526044810187905290519293506001600160a01b039091169163e12ab1af9160648082019260009290919082900301818387803b15801561301f57600080fd5b505af1158015613033573d6000803e3d6000fd5b50505050505b60018088015460008b815260208052604081208181559283018190556002830180546001600160a81b03191690559091906130776003830182615c0d565b50506000998a52602080526040909920600101989098555050505050505050565b60225481565b60005461010090046001600160a01b031633146130ec5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b6005546016546040805163a3b1d8cb60e01b8152600481018590526024810192909252516001600160a01b039092169163a3b1d8cb9160448082019260009290919082900301818387803b15801561314357600080fd5b505af1158015613157573d6000803e3d6000fd5b50505050606481111561319b576040805162461bcd60e51b8152602060048201526007602482015266746f6f2062696760c81b604482015290519081900360640190fd5b601655565b60008113156131f95760195460ff166131f9576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b6000828152601a60205260409020600601546001600160a01b03163314613262576040805162461bcd60e51b8152602060048201526018602482015277496e76616c696420636f6e7472616374206164647265737360401b604482015290519081900360640190fd5b6124ae81600080614ba0565b60005461010090046001600160a01b031633146132bc5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b60008111613311576040805162461bcd60e51b815260206004820181905260248201527f426c6f636b7320696e74657276616c206d757374206265206e6f6e2d7a65726f604482015290519081900360640190fd5b600e55565b601c5490565b613324614c5c565b6000858152601a60205260409020805460039091015415801561334657508015155b613397576040805162461bcd60e51b815260206004820181905260248201527f496e76616c69642076616c696461746f7220666f7220616e2061756374696f6e604482015290519081900360640190fd5b336000818152601b60209081526040918290205460065483516370a0823160e01b81526004810195909552925190936001600160a01b03909316926370a08231926024808301939192829003018186803b1580156133f457600080fd5b505afa158015613408573d6000803e3d6000fd5b505050506040513d602081101561341e57600080fd5b505115801561342f57506000198114155b613477576040805162461bcd60e51b8152602060048201526014602482015273416c72656164792075736564206164647265737360601b604482015290519081900360640190fd5b60095460185480158061348a5750818111155b6134cd576040805162461bcd60e51b815260206004820152600f60248201526e10dbdbdb191bdddb881c195c9a5bd9608a1b604482015290519081900360640190fd5b601554600a546134e3908263ffffffff61473e16565b60008b8152601a602052604090206002015461350690859063ffffffff61475016565b8161350d57fe5b0610613559576040805162461bcd60e51b8152602060048201526016602482015275125b9d985b1a5908185d58dd1a5bdb881c195c9a5bd960521b604482015290519081900360640190fd5b6000898152601a602052604090206006015484906001600160a01b031680156135cf576135cc816001600160a01b031663a446c2db6040518163ffffffff1660e01b815260040160206040518083038186803b1580156135b857600080fd5b505afa158015612b60573d6000803e3d6000fd5b91505b60008b8152602080526040902080546135e8848261597c565b93508b8410613630576040805162461bcd60e51b815260206004820152600f60248201526e26bab9ba103134b2103434b3b432b960891b604482015290519081900360640190fd5b600354604080516323b872dd60e01b8152336004820152306024820152604481018f905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b15801561368a57600080fd5b505af115801561369e573d6000803e3d6000fd5b505050506040513d60208110156136b457600080fd5b5051613700576040805162461bcd60e51b8152602060048201526016602482015275151c985b9cd9995c88185b5bdd5b9d0819985a5b195960521b604482015290519081900360640190fd5b80156137d25760035460028301546040805163a9059cbb60e01b81526001600160a01b039283166004820152602481018590529051919092169163a9059cbb9160448083019260209291908290030181600087803b15801561376157600080fd5b505af1158015613775573d6000803e3d6000fd5b505050506040513d602081101561378b57600080fd5b50516137d2576040805162461bcd60e51b8152602060048201526011602482015270109a59081c995d1d5c9b8819985a5b1959607a1b604482015290519081900360640190fd5b8b8255600282018054336001600160a01b03199091161760ff60a01b1916600160a01b8d15150217905561380a600383018b8b615c51565b50600560009054906101000a90046001600160a01b03166001600160a01b0316630934a6df8e8a8f6040518463ffffffff1660e01b8152600401808481526020018381526020018281526020019350505050600060405180830381600087803b15801561387657600080fd5b505af115801561388a573d6000803e3d6000fd5b5050505050505050505050505050505050565b60005461010090046001600160a01b031633146138eb5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b6138f361598c565b565b60085490565b60005461010090046001600160a01b031633146139495760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b600c91909155600d55565b6000838152601a60205260408120600601546001600160a01b03163314806139f357506004805460408051631ab0168360e31b8152905133936001600160a01b039093169263d580b41892808201926020929091829003018186803b1580156139bc57600080fd5b505afa1580156139d0573d6000803e3d6000fd5b505050506040513d60208110156139e657600080fd5b50516001600160a01b0316145b613a3f576040805162461bcd60e51b8152602060048201526018602482015277496e76616c696420636f6e7472616374206164647265737360401b604482015290519081900360640190fd5b6003546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018790529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561283b57600080fd5b6007546001600160a01b031681565b60005461010090046001600160a01b03163314613af25760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b60008111613aff57600080fd5b600554600b5460408051632dbe9d3160e21b8152600481018590526024810192909252516001600160a01b039092169163b6fa74c49160448082019260009290919082900301818387803b158015613b5657600080fd5b505af1158015613b6a573d6000803e3d6000fd5b505050600b9190915550565b60145481565b60005460ff1681565b336000908152601b6020526040902054613b9e816118ea565b613be1576040805162461bcd60e51b815260206004820152600f60248201526e3737ba1030903b30b634b230ba37b960891b604482015290519081900360640190fd5b6000818152601a60205260409020600601546001600160a01b031680613c47576040805162461bcd60e51b815260206004820152601660248201527519195b1959d85d1a5bdb881b9bdd08195b98589b195960521b604482015290519081900360640190fd5b604080516303dd464160e51b8152841515600482015290516001600160a01b03831691637ba8c82091602480830192600092919082900301818387803b158015613c9057600080fd5b505af1158015613ca4573d6000803e3d6000fd5b50505050505050565b60216020526000908152604090205481565b80613cc981614b16565b6000828152601a60205260409020600301548015801590613cff5750600954600854613cfc90839063ffffffff61473e16565b11155b8015613d32575060036000848152601a6020526040902060060154600160a01b900460ff166003811115613d2f57fe5b14155b613d3b57600080fd5b6000838152601a6020526040812054601154909190613d60908363ffffffff61475016565b601181905560065460408051630852cd8d60e31b81526004810189905290519293506001600160a01b03909116916342966c689160248082019260009290919082900301818387803b158015613db557600080fd5b505af1158015613dc9573d6000803e3d6000fd5b5050506000868152601a6020818152604080842060058101546001600160a01b039081168652601b845282862060001990558b8652938352600601805460ff60a01b1916600360a01b179055600354815163a9059cbb60e01b81523360048201526024810189905291519316945063a9059cbb93604480830194928390030190829087803b158015613e5a57600080fd5b505af1158015613e6e573d6000803e3d6000fd5b505050506040513d6020811015613e8457600080fd5b5051613ecf576040805162461bcd60e51b8152602060048201526015602482015274151c985b9cd9995c881cdd185ad94819985a5b1959605a1b604482015290519081900360640190fd5b6005546040805163ae2e26b160e01b815233600482015260248101889052604481018590526064810184905290516001600160a01b039092169163ae2e26b19160848082019260009290919082900301818387803b15801561185357600080fd5b601c54601d5482565b60005461010090046001600160a01b03163314613f875760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b60008111613f9457600080fd5b600554600a5460408051635071805360e11b8152600481018590526024810192909252516001600160a01b039092169163a0e300a69160448082019260009290919082900301818387803b158015613feb57600080fd5b505af1158015613fff573d6000803e3d6000fd5b505050600a82905550600881905561401e81600463ffffffff61470616565b60158190556009546140359163ffffffff61473e16565b60185550565b614043612a68565b61404c57600080fd5b6001600160a01b03811661405f57600080fd5b6002546040516001600160a01b038084169216907f211c9015fc81c0dbd45bd99f0f29fc1c143bfd53442d5ffd722bbbef7a887fe990600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000908152601a602052604090205490565b6005546001600160a01b031681565b60005461010090046001600160a01b0316331461412a5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b6019805460ff1916911515919091179055565b614145612a68565b61414e57600080fd5b612ad9816157bb565b8161416181614b16565b600061416c83615998565b90506001600160a01b0381161580159061419c57506001600160a01b0381166000908152601b6020526040902054155b6141de576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b604482015290519081900360640190fd5b600954600f546000868152602160205260409020546142029163ffffffff61473e16565b811015614256576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636865636b706f696e74206e756d62657221000000000000604482015290519081900360640190fd5b6000858152601a602090815260408083206005908101549054915163b80fbce560e01b8152600481018a81526001600160a01b039283166024830181905288841660448401526080606484019081528b5160848501528b519197949095169563b80fbce5958d9589958c958f95909460a490920192918601918190849084905b838110156142ee5781810151838201526020016142d6565b50505050905090810190601f16801561431b5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b15801561433d57600080fd5b505af1158015614351573d6000803e3d6000fd5b5050506001600160a01b039182166000908152601b60209081526040808320600019905595909316808252858220899055978152601a835284812060050180546001600160a01b03191690981790975550602190529320929092555050565b60005461010090046001600160a01b031633146143fe5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b306001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561444157600080fd5b505afa158015614455573d6000803e3d6000fd5b505050506040513d602081101561446b57600080fd5b50516001600160a01b0316146144b25760405162461bcd60e51b8152600401808060200182810382526026815260200180615d6f6026913960400191505060405180910390fd5b6000918252601a602052604090912060060180546001600160a01b0319166001600160a01b03909216919091179055565b60005461010090046001600160a01b031633146145315760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b600954614035908263ffffffff61473e16565b60005461010090046001600160a01b031633146145925760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b6138f36159ed565b6008831080156145aa5750600782115b6145ef576040805162461bcd60e51b815260206004820152601160248201527024b73b30b634b21036b4b3b930ba34b7b760791b604482015290519081900360640190fd5b6000838152601a6020526040808220600601548151636e7ce59160e01b81523360048201526024810185905291516001600160a01b0390911692636e7ce591926044808201939182900301818387803b15801561464b57600080fd5b505af115801561465f573d6000803e3d6000fd5b5050506000838152601a6020526040808220600601548151632830728d60e21b81523360048201526024810186905291516001600160a01b03909116935063a0c1ca349260448084019391929182900301818387803b158015613c9057600080fd5b600d5481565b6003546001600160a01b031681565b6000826146e557506000614700565b828202828482816146f257fe5b04146146fd57600080fd5b90505b92915050565b600080821161471457600080fd5b600082848161471f57fe5b04949350505050565b600081831061473757816146fd565b5090919050565b6000828201838110156146fd57600080fd5b60008282111561475f57600080fd5b50900390565b600954600061477b82600163ffffffff61473e16565b9050614785615ccf565b506000818152601e602090815260408083208151808301909252805480835260019091015492820183905290926147bc9290614ba0565b506000918252601e6020526040822082815560010191909155600955565b60008080805b84518167ffffffffffffffff161015614a5a57600073ad758ddd05c851abfe184d6b1be0a5f1b3bcab786377d32e94886148268967ffffffffffffffff871660416159fc565b6040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614878578181015183820152602001614860565b50505050905090810190601f1680156148a55780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b1580156148c357600080fd5b505af41580156148d7573d6000803e3d6000fd5b505050506040513d60208110156148ed57600080fd5b50516001600160a01b038082166000818152601b6020526040902054929350908516141561491c575050614a5a565b614925816118ea565b80156149425750836001600160a01b0316826001600160a01b0316115b15614a50576000818152601a60205260408120600681015493955085939091906001600160a01b03168015614a0257806001600160a01b031663b37f25908d8f61498b886140bb565b6040518463ffffffff1660e01b8152600401808481526020018381526020018281526020019350505050602060405180830381600087803b1580156149cf57600080fd5b505af11580156149e3573d6000803e3d6000fd5b505050506040513d60208110156149f957600080fd5b50519150614a3a565b82600001549150614a34614a238e61122f8f866146d690919063ffffffff16565b60018501549063ffffffff61473e16565b60018401555b614a4a888363ffffffff61473e16565b97505050505b50506041016147e0565b50614a79614a66613316565b600b5461122f908563ffffffff6146d616565b601354909650614a8f908763ffffffff61473e16565b601355614ac16001614ab5600361122f6002614aa9613316565b9063ffffffff6146d616565b9063ffffffff61473e16565b821015614b0b576040805162461bcd60e51b8152602060048201526013602482015272322f332b31206e6f6e2d6d616a6f726974792160681b604482015290519081900360640190fd5b509395945050505050565b600654604080516331a9108f60e11b815260048101849052905133926001600160a01b031691636352211e916024808301926020929190829003018186803b158015614b6157600080fd5b505afa158015614b75573d6000803e3d6000fd5b505050506040513d6020811015614b8b57600080fd5b50516001600160a01b031614612ad957600080fd5b80614c3a576000831315614bc957601c54614bc1908463ffffffff61473e16565b601c55614bed565b6000831215614bed57601c54614be990600085900363ffffffff61475016565b601c555b6000821315614c1157601d54614c09908363ffffffff61473e16565b601d55614c35565b6000821215614c3557601d54614c3190600084900363ffffffff61475016565b601d555b611dd3565b6000818152601e60205260409020805484018155600101805483019055505050565b60005460ff16156138f3576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b6000828152601a602052604081205490614cb68461244e565b6000858152601a6020526040812060038101869055600181015460069091015492935090916001600160a01b03168015614dae576000819050614d41816001600160a01b03166332ba2e536040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614d2d57600080fd5b505af1158015612d6c573d6000803e3d6000fd5b9250806001600160a01b031663753868e36040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614d7e57600080fd5b505af1158015614d92573d6000803e3d6000fd5b505050506040513d6020811015614da857600080fd5b50519350505b614db987858461582a565b6000600954871115614dcb5786614dce565b60005b9050614de284870160000360001983614ba0565b60055460408051635e04d48360e01b81526001600160a01b038881166004830152602482018c9052604482018b9052606482018a905291519190921691635e04d48391608480830192600092919082900301818387803b158015614e4557600080fd5b505af1158015614e59573d6000803e3d6000fd5b505050505050505050505050565b600d54821015614ebe576040805162461bcd60e51b815260206004820152601760248201527f4e6f7420656e6f756768206865696d64616c6c20666565000000000000000000604482015290519081900360640190fd5b6003546001600160a01b03166323b872dd3330614ee1868663ffffffff61473e16565b6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015614f4957600080fd5b505af1158015614f5d573d6000803e3d6000fd5b505050506040513d6020811015614f7357600080fd5b5051614fbc576040805162461bcd60e51b8152602060048201526013602482015272119959481d1c985b9cd9995c8819985a5b1959606a1b604482015290519081900360640190fd5b602254614fcf908363ffffffff61473e16565b6022556005546040805163a449d79560e01b81526001600160a01b038681166004830152602482018690529151919092169163a449d79591604480830192600092919082900301818387803b158015613c9057600080fd5b60008061503383615998565b90506001600160a01b0381161580159061506357506001600160a01b0381166000908152601b6020526040902054155b6150a5576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b604482015290519081900360640190fd5b6009546012546005546011546001600160a01b03909116906000906150d0908a63ffffffff61473e16565b9050806011819055506040518061010001604052808a8152602001600081526020018581526020016000815260200160008152602001866001600160a01b03168152602001896151215760006151ad565b600754600480546040805163d4ad267360e01b81529283018990526001600160a01b03888116602485015291821660448401525192169163d4ad2673916064808201926020929091908290030181600087803b15801561518057600080fd5b505af1158015615194573d6000803e3d6000fd5b505050506040513d60208110156151aa57600080fd5b50515b6001600160a01b03168152602001600190526000848152601a60209081526040918290208351815590830151600182015590820151600282015560608201516003808301919091556080830151600483015560a08301516005830180546001600160a01b039283166001600160a01b03199182161790915560c08501516006850180549190931691161780825560e08501519260ff60a01b1990911690600160a01b90849081111561525b57fe5b0217905550505060008381526021602052604080822086905560065481516340c10f1960e01b81526001600160a01b038e8116600483015260248201889052925192909116926340c10f199260448084019382900301818387803b1580156152c257600080fd5b505af11580156152d6573d6000803e3d6000fd5b5050506001600160a01b0386166000908152601b6020526040812085905561530391508a90600190614ba0565b836020600085815260200190815260200160002060010181905550816001600160a01b03166333a8383c868986888e876040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b0316815260200180602001868152602001858152602001848152602001838152602001828103825287818151815260200191508051906020019080838360005b838110156153af578181015183820152602001615397565b50505050905090810190601f1680156153dc5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561540057600080fd5b505af1158015615414573d6000803e3d6000fd5b5050505061542c60018461473e90919063ffffffff16565b601255509098975050505050505050565b615445615ccf565b506040805180820190915281518152602082810190820152919050565b606061546d82615a7b565b61547657600080fd5b600061548183615ab5565b90506060816040519080825280602002602001820160405280156154bf57816020015b6154ac615ccf565b8152602001906001900390816154a45790505b50905060006154d18560200151615b11565b60208601510190506000805b84811015615528576154ee83615b74565b915060405180604001604052808381526020018481525084828151811061551157fe5b6020908102919091010152918101916001016154dd565b509195945050505050565b80516000901580159061554857508151602110155b61555157600080fd5b60006155608360200151615b11565b8351602080860151830180519394509184900392919083101561558a57826020036101000a820491505b50949350505050565b80516000906001146155a457600080fd5b6020820151805160001a9081156155bc5760016155bf565b60005b949350505050565b6000828152601a602052604081206006015481906001600160a01b03161561566d576000848152601a6020908152604080832060060154815163753868e360e01b815291516001600160a01b039091169363753868e393600480850194919392918390030190829087803b15801561563e57600080fd5b505af1158015615652573d6000803e3d6000fd5b505050506040513d602081101561566857600080fd5b505190505b600954615680818563ffffffff61473e16565b6000868152601a602052604080822060048082019490945560068101805460ff60a01b1916600160a11b1790556005805491015482516381dc101b60e01b81529485018a9052602485018690526001600160a01b03908116604486015291519116926381dc101b92606480830193919282900301818387803b15801561570557600080fd5b505af1158015615719573d6000803e3d6000fd5b5050506000868152601a602052604090205461244591508363ffffffff61473e16565b60225461574f908263ffffffff61475016565b6022556005546040805163122b648160e01b81526001600160a01b038581166004830152602482018590529151919092169163122b648191604480830192600092919082900301818387803b1580156157a757600080fd5b505af115801561205a573d6000803e3d6000fd5b6001600160a01b0381166157ce57600080fd5b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b60145461583d908263ffffffff61473e16565b6014556000838152601a60209081526040808320600101839055600354815163a9059cbb60e01b81526001600160a01b038781166004830152602482018790529251929091169363a9059cbb9360448084019491939192918390030190829087803b1580156158ab57600080fd5b505af11580156158bf573d6000803e3d6000fd5b505050506040513d60208110156158d557600080fd5b505161591e576040805162461bcd60e51b8152602060048201526013602482015272496e737566666963656e74207265776172647360681b604482015290519081900360640190fd5b60055460145460408051635b42d93560e11b815260048101879052602481018590526044810192909252516001600160a01b039092169163b685b26a9160648082019260009290919082900301818387803b158015613c9057600080fd5b60008183101561473757816146fd565b6000805460ff19169055565b600081516040146159e1576040805162461bcd60e51b815260206004820152600e60248201526d496e76616c6964207075626b657960901b604482015290519081900360640190fd5b50805160209091012090565b6000805460ff19166001179055565b606081830184511015615a0e57600080fd5b606082158015615a295760405191506020820160405261558a565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015615a62578051835260209283019201615a4a565b5050858452601f01601f19166040525050949350505050565b8051600090615a8c575060006115b0565b6020820151805160001a9060c0821015615aab576000925050506115b0565b5060019392505050565b8051600090615ac6575060006115b0565b60008090506000615ada8460200151615b11565b602085015185519181019250015b80821015615b0857615af982615b74565b60019093019290910190615ae8565b50909392505050565b8051600090811a6080811015615b2b5760009150506115b0565b60b8811080615b46575060c08110801590615b46575060f881105b15615b555760019150506115b0565b60c0811015615b695760b5190190506115b0565b60f5190190506115b0565b80516000908190811a6080811015615b8f5760019150615c06565b60b8811015615ba457607e1981019150615c06565b60c0811015615bd15760b78103600185019450806020036101000a85510460018201810193505050615c06565b60f8811015615be65760be1981019150615c06565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b50805460018160011615610100020316600290046000825580601f10615c335750612ad9565b601f016020900490600052602060002090810190612ad99190615ce9565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615c925782800160ff19823516178555615cbf565b82800160010185558215615cbf579182015b82811115615cbf578235825591602001919060010190615ca4565b50615ccb929150615ce9565b5090565b604051806040016040528060008152602001600081525090565b61290791905b80821115615ccb5760008155600101615cef56fe56616c696461746f7220736574205468726573686f6c64206578636565646564214f6e6c7920626964646572206f722076616c696461746f722063616e20636f6e6669726d4f6e6c7920676f7665726e616e636520636f6e747261637420697320617574686f72697a65644f776e6572206f6620636f6e7472616374206d757374206265207374616b654d616e61676572a265627a7a723158205303fd765be1bd98f895304344671726e733bd897ca8b4c4e93a97b01f9a248864736f6c63430005110032
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104b75760003560e01c80637b10399911610278578063bc8756a91161015c578063eceec1d3116100ce578063f4547a4d11610092578063f4547a4d14611124578063f771fc8714611150578063f83d08ba1461116d578063fb1ef52c14611175578063fba58f341461119e578063fc0c546a146111a6576104b7565b8063eceec1d31461100f578063f24ccbfe1461102c578063f28699fa14611034578063f2fde38b14611053578063f41a964214611079576104b7565b8063d6de07d011610120578063d6de07d014610f6b578063d7f5549d14610f8a578063d86d53e714610fa7578063e59ee0c614610fc4578063e6692f4914610fcc578063e8afa8e814610fe9576104b7565b8063bc8756a914610f04578063c45a015514610f36578063cbf383d514610f3e578063cd6b838814610f5b578063cf30901214610f63576104b7565b8063987ab9db116101f5578063a440ab1e116101b9578063a440ab1e14610e29578063a476907114610e46578063a685487714610e4e578063a69df4b514610ed1578063a7ab696114610ed9578063b1d23f0214610ee1576104b7565b8063987ab9db14610db657806399d18f6f14610dbe5780639a8a624314610de15780639b33f43414610de95780639ff1150014610e06576104b7565b80638da5cb5b1161023c5780638da5cb5b14610d645780638f32d59b14610d6c578063900cf0cf14610d745780639146014914610d7c5780639342c8f414610d99576104b7565b80637b10399914610ce55780637d66975214610ced5780637f952d9514610cf5578063817b1cd214610cfd5780638a29e2de14610d05576104b7565b806341b3d1851161039f5780635e47655f1161031c5780636901b253116102e05780636901b25314610c6d5780637060054d14610c9f578063715018a614610ca75780637667180814610caf57806377939d1014610cb757806378f84a4414610cbf576104b7565b80635e47655f14610a985780636352211e14610b3c5780636365679814610b595780636400e38514610b8557806368cb812a14610bbd576104b7565b80635325e144116103635780635325e1441461099c57806354b8c60114610a635780635508d8e114610a6b57806356342d8c14610a735780635aa6e67514610a90576104b7565b806341b3d185146108975780634b341aed1461089f5780634e3c83f1146108c55780634fd101d7146108cd5780634fdd20f1146108d5576104b7565b806317c2b9101161043857806328cc4e41116103fc57806328cc4e41146107675780632e17de781461079257806331c2273b146107af57806334274586146107d357806335aa2e44146107db5780633862da0b14610871576104b7565b806317c2b910146106d35780631dd6b9b1146106db57806325316411146106f857806325726df2146107005780632649263a14610736576104b7565b80630ebb172a1161047f5780630ebb172a14610645578063144fa6d71461064d57806316827b1b14610673578063174e683214610690578063178c2c83146106b6576104b7565b8063028c4c67146104bc578063066647a01461054157806306cfb104146106185780630cccfc58146106355780630e15561a1461063d575b600080fd5b61053f600480360360808110156104d257600080fd5b813591602081013591604082013515159190810190608081016060820135600160201b81111561050157600080fd5b82018360208201111561051357600080fd5b803590602001918460018302840111600160201b8311171561053457600080fd5b5090925090506111ae565b005b610606600480360360a081101561055757600080fd5b8135916020810135916040820135916001600160a01b036060820135169181019060a081016080820135600160201b81111561059257600080fd5b8201836020820111156105a457600080fd5b803590602001918460018302840111600160201b831117156105c557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506111f8945050505050565b60408051918252519081900360200190f35b61053f6004803603602081101561062e57600080fd5b5035611371565b6106066113c4565b6106066113ca565b6106066113d0565b61053f6004803603602081101561066357600080fd5b50356001600160a01b03166113d6565b61053f6004803603602081101561068957600080fd5b5035611459565b610606600480360360208110156106a657600080fd5b50356001600160a01b031661152b565b61053f600480360360208110156106cc57600080fd5b50356115b5565b610606611872565b61053f600480360360208110156106f157600080fd5b5035611878565b6106066118cb565b61071d6004803603602081101561071657600080fd5b50356118d1565b6040805192835260208301919091528051918290030190f35b6107536004803603602081101561074c57600080fd5b50356118ea565b604080519115158252519081900360200190f35b61053f6004803603606081101561077d57600080fd5b5080359060208101359060400135151561196b565b61053f600480360360208110156107a857600080fd5b5035611cac565b6107b7611dd8565b604080516001600160a01b039092168252519081900360200190f35b610606611de7565b6107f8600480360360208110156107f157600080fd5b5035611ded565b60405180898152602001888152602001878152602001868152602001858152602001846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b0316815260200182600381111561085657fe5b60ff1681526020019850505050505050505060405180910390f35b6106066004803603602081101561088757600080fd5b50356001600160a01b0316611e43565b610606611e55565b610606600480360360208110156108b557600080fd5b50356001600160a01b0316611e5b565b610606611f92565b610606611f98565b61053f600480360360a08110156108eb57600080fd5b6001600160a01b0382351691602081013591604082013591606081013515159181019060a081016080820135600160201b81111561092857600080fd5b82018360208201111561093a57600080fd5b803590602001918460018302840111600160201b8311171561095b57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611f9e945050505050565b6109b9600480360360208110156109b257600080fd5b5035612062565b60405180868152602001858152602001846001600160a01b03166001600160a01b031681526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610a24578181015183820152602001610a0c565b50505050905090810190601f168015610a515780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b610753612128565b610606612131565b6107b760048036036020811015610a8957600080fd5b5035612137565b6107b7612155565b61060660048036036020811015610aae57600080fd5b810190602081018135600160201b811115610ac857600080fd5b820183602082011115610ada57600080fd5b803590602001918460018302840111600160201b83111715610afb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612169945050505050565b6107b760048036036020811015610b5257600080fd5b503561244e565b61053f60048036036040811015610b6f57600080fd5b506001600160a01b03813516906020013561249a565b61053f60048036036060811015610b9b57600080fd5b506001600160a01b0381358116916020810135821691604090910135166124b2565b61053f60048036036060811015610bd357600080fd5b813591602081013591810190606081016040820135600160201b811115610bf957600080fd5b820183602082011115610c0b57600080fd5b803590602001918460018302840111600160201b83111715610c2c57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061253f945050505050565b61075360048036036060811015610c8357600080fd5b50803590602081013590604001356001600160a01b0316612776565b61060661286f565b61053f612875565b6106066128d0565b6106066128d6565b61060660048036036020811015610cd557600080fd5b50356001600160a01b03166128dc565b6107b76128ee565b6106066128fd565b610606612903565b61060661290a565b61053f6004803603610100811015610d1c57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c082013581169160e0013516612910565b6107b7612a59565b610753612a68565b610606612a79565b61053f60048036036020811015610d9257600080fd5b5035612a7f565b61053f60048036036020811015610daf57600080fd5b5035612adc565b6107b7612b93565b61053f60048036036040811015610dd457600080fd5b5080359060200135612ba2565b610606613098565b61053f60048036036020811015610dff57600080fd5b503561309e565b61053f60048036036040811015610e1c57600080fd5b50803590602001356131a0565b61053f60048036036020811015610e3f57600080fd5b503561326e565b610606613316565b61053f60048036036080811015610e6457600080fd5b813591602081013591604082013515159190810190608081016060820135600160201b811115610e9357600080fd5b820183602082011115610ea557600080fd5b803590602001918460018302840111600160201b83111715610ec657600080fd5b50909250905061331c565b61053f61389d565b6106066138f5565b61053f60048036036040811015610ef757600080fd5b50803590602001356138fb565b61075360048036036060811015610f1a57600080fd5b50803590602081013590604001356001600160a01b0316613954565b6107b7613a95565b61053f60048036036020811015610f5457600080fd5b5035613aa4565b610606613b76565b610753613b7c565b61053f60048036036020811015610f8157600080fd5b50351515613b85565b61060660048036036020811015610fa057600080fd5b5035613cad565b61053f60048036036020811015610fbd57600080fd5b5035613cbf565b61071d613f30565b61053f60048036036020811015610fe257600080fd5b5035613f39565b61053f60048036036020811015610fff57600080fd5b50356001600160a01b031661403b565b6106066004803603602081101561102557600080fd5b50356140bb565b6107b76140cd565b61053f6004803603602081101561104a57600080fd5b503515156140dc565b61053f6004803603602081101561106957600080fd5b50356001600160a01b031661413d565b61053f6004803603604081101561108f57600080fd5b81359190810190604081016020820135600160201b8111156110b057600080fd5b8201836020820111156110c257600080fd5b803590602001918460018302840111600160201b831117156110e357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550614157945050505050565b61053f6004803603604081101561113a57600080fd5b50803590602001356001600160a01b03166143b0565b61053f6004803603602081101561116657600080fd5b50356144e3565b61053f614544565b61053f6004803603606081101561118b57600080fd5b508035906020810135906040013561459a565b6106066146c1565b6107b76146c7565b6111f13386868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f9e92505050565b5050505050565b6002546000906001600160a01b0316331461121257600080fd5b600061123b600e5461122f600b548a6146d690919063ffffffff16565b9063ffffffff61470616565b9050611249600b5482614728565b90506000611267606461122f601654856146d690919063ffffffff16565b6001600160a01b038087166000908152601b60209081526040808320548352601a909152902060068101549293509116156113115760068101548154604080516301a6632160e31b8152600481018690526024810192909252516001600160a01b0390921691630d3319089160448082019260009290919082900301818387803b1580156112f457600080fd5b505af1158015611308573d6000803e3d6000fd5b5050505061132c565b6001810154611326908363ffffffff61473e16565b60018201555b61133c838363ffffffff61475016565b92506000611348613316565b60178990559050611357614765565b61136381858b896147da565b9a9950505050505050505050565b60005461010090046001600160a01b031633146113bf5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b600f55565b60155481565b60135481565b60085481565b60005461010090046001600160a01b031633146114245760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b6001600160a01b03811661143757600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60005461010090046001600160a01b031633146114a75760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b600081116114b457600080fd5b60055460105460408051630f1980a560e41b8152600481018590526024810192909252516001600160a01b039092169163f1980a509160448082019260009290919082900301818387803b15801561150b57600080fd5b505af115801561151f573d6000803e3d6000fd5b50505060109190915550565b60065460408051632f745c5960e01b81526001600160a01b038481166004830152600060248301819052925192931691632f745c5991604480820192602092909190829003018186803b15801561158157600080fd5b505afa158015611595573d6000803e3d6000fd5b505050506040513d60208110156115ab57600080fd5b505190505b919050565b806115bf81614b16565b60026000838152601a6020526040902060060154600160a01b900460ff1660038111156115e857fe5b1461163a576040805162461bcd60e51b815260206004820152601760248201527f56616c696461746f72206973206e6f74206a61696c6564000000000000000000604482015290519081900360640190fd5b6000828152601a60205260409020600301541561169e576040805162461bcd60e51b815260206004820152601b60248201527f56616c696461746f7220616c726561647920756e7374616b696e670000000000604482015290519081900360640190fd5b6009546000838152601a6020526040902060040154811015611700576040805162461bcd60e51b8152602060048201526016602482015275125b98dbdb5c1b195d19481a985a5b081c195c9a5bd960521b604482015290519081900360640190fd5b6000838152601a6020526040902054600c5481101561171e57600080fd5b6000848152601a60205260408120600601546001600160a01b0316156117c2576000858152601a602090815260408083206006015481516322f0f2f960e01b815291516001600160a01b03909116936322f0f2f993600480850194919392918390030190829087803b15801561179357600080fd5b505af11580156117a7573d6000803e3d6000fd5b505050506040513d60208110156117bd57600080fd5b505190505b6117de6117d5838363ffffffff61473e16565b60016000614ba0565b6000858152601a602052604080822060068101805460ff60a01b1916600160a01b17905560058054910154825163f92ec5af60e01b8152600481018a90526001600160a01b039182166024820152925191169263f92ec5af926044808201939182900301818387803b15801561185357600080fd5b505af1158015611867573d6000803e3d6000fd5b505050505050505050565b60175481565b60005461010090046001600160a01b031633146118c65760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b600955565b600e5481565b601e602052600090815260409020805460019091015482565b6000818152601a6020526040812060028101546003820154825460069093015460095492939192600160a01b90910460ff16908215801590611936575084158015906119365750808511155b8015611949575083158061194957508084115b80156119605750600182600381111561195e57fe5b145b979650505050505050565b611973614c5c565b8261197d81614b16565b6000848152601a6020526040902060030154156119d7576040805162461bcd60e51b81526020600482015260136024820152724e6f20757365206f662072657374616b696e6760681b604482015290519081900360640190fd5b8215611aac57600354604080516323b872dd60e01b81523360048201523060248201526044810186905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b158015611a3757600080fd5b505af1158015611a4b573d6000803e3d6000fd5b505050506040513d6020811015611a6157600080fd5b5051611aac576040805162461bcd60e51b8152602060048201526015602482015274151c985b9cd9995c881cdd185ad94819985a5b1959605a1b604482015290519081900360640190fd5b8115611b87576000848152601a6020526040902060010154611ad590849063ffffffff61473e16565b6000858152601a60205260409020600601549093506001600160a01b03168015611b7357611b70816001600160a01b03166332ba2e536040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b3757600080fd5b505af1158015611b4b573d6000803e3d6000fd5b505050506040513d6020811015611b6157600080fd5b5051859063ffffffff61473e16565b93505b506000848152601a60205260408120600101555b601154600090611b9d908563ffffffff61473e16565b60118190556000868152601a6020526040902054909150611bc4908563ffffffff61473e16565b6000868152601a6020526040812091909155611be290859080614ba0565b6005546040805163532e19a960e01b81526004810188905290516001600160a01b039092169163532e19a99160248082019260009290919082900301818387803b158015611c2f57600080fd5b505af1158015611c43573d6000803e3d6000fd5b50506005546000888152601a6020526040808220548151631585a9f360e21b8152600481018c905260248101919091526044810187905290516001600160a01b039093169450635616a7cc93506064808201939182900301818387803b15801561185357600080fd5b80611cb681614b16565b600082815260208052604090205415611d16576040805162461bcd60e51b815260206004820152601b60248201527f5761697420666f722061756374696f6e20636f6d706c6574696f6e0000000000604482015290519081900360640190fd5b6000828152601a602052604090206002015415801590611d4557506000828152601a6020526040902060030154155b8015611da7575060016000838152601a6020526040902060060154600160a01b900460ff166003811115611d7557fe5b1480611da7575060026000838152601a6020526040902060060154600160a01b900460ff166003811115611da557fe5b145b611db057600080fd5b600954600090611dc790600163ffffffff61473e16565b9050611dd38382614c9d565b505050565b6006546001600160a01b031681565b60165481565b601a602052600090815260409020805460018201546002830154600384015460048501546005860154600690960154949593949293919290916001600160a01b039081169190811690600160a01b900460ff1688565b601b6020526000908152604090205481565b600c5481565b60006001600160a01b0382161580611ee95750600654604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b158015611ebb57600080fd5b505afa158015611ecf573d6000803e3d6000fd5b505050506040513d6020811015611ee557600080fd5b5051155b15611ef6575060006115b0565b60065460408051632f745c5960e01b81526001600160a01b0385811660048301526000602483018190529251601a949190911691632f745c59916044808301926020929190829003018186803b158015611f4f57600080fd5b505afa158015611f63573d6000803e3d6000fd5b505050506040513d6020811015611f7957600080fd5b5051815260208101919091526040016000205492915050565b600f5481565b60105481565b611fa6614c5c565b601054611fb1612903565b10611fed5760405162461bcd60e51b8152600401808060200182810382526021815260200180615d046021913960400191505060405180910390fd5b600c548411612043576040805162461bcd60e51b815260206004820152601960248201527f6d696e206465706f736974206c696d6974206661696c65642100000000000000604482015290519081900360640190fd5b61204e858486614e67565b61205a85858484615027565b505050505050565b60208080526000918252604091829020805460018083015460028085015460038601805489516101009682161596909602600019011692909204601f8101889004880285018801909852878452939691956001600160a01b03851695600160a01b90950460ff169493929083018282801561211e5780601f106120f35761010080835404028352916020019161211e565b820191906000526020600020905b81548152906001019060200180831161210157829003601f168201915b5050505050905085565b60195460ff1681565b60125481565b6000908152601a60205260409020600601546001600160a01b031690565b60005461010090046001600160a01b031681565b6004805460408051631ab0168360e31b8152905160009333936001600160a01b03169263d580b4189281830192602092829003018186803b1580156121ad57600080fd5b505afa1580156121c1573d6000803e3d6000fd5b505050506040513d60208110156121d757600080fd5b50516001600160a01b031614612234576040805162461bcd60e51b815260206004820181905260248201527f53656e646572206d75737420626520736c617368696e67206d616e6167657221604482015290519081900360640190fd5b60606122476122428461543d565b615462565b905060008080805b845181101561242357606061227686838151811061226957fe5b6020026020010151615462565b905060006122978260008151811061228a57fe5b6020026020010151615533565b905060006122ab8360018151811061228a57fe5b90506122bd858263ffffffff61473e16565b6000838152601a60205260409020600601549095506001600160a01b031615612385576000828152601a602090815260408083206006810154905482516314454c8560e31b815260048101919091526024810186905291516001600160a01b039091169263a22a6428926044808201939182900301818787803b15801561234357600080fd5b505af1158015612357573d6000803e3d6000fd5b505050506040513d602081101561236d57600080fd5b50519050612381828263ffffffff61475016565b9150505b6000828152601a60205260408120546123a4908363ffffffff61475016565b6000848152601a602052604090208190559050806123cd576123c883600954614c9d565b612413565b6123ea846002815181106123dd57fe5b6020026020010151615593565b156124135761240a6123fd8460016155c7565b889063ffffffff61473e16565b60019098019796505b50506001909201915061224f9050565b50612445612437828463ffffffff61473e16565b600003846000036000614ba0565b95945050505050565b600654604080516331a9108f60e11b81526004810184905290516000926001600160a01b031691636352211e916024808301926020929190829003018186803b15801561158157600080fd5b6124a2614c5c565b6124ae82826000614e67565b5050565b60005461010090046001600160a01b031633146125005760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b600680546001600160a01b039485166001600160a01b031991821617909155600580549385169382169390931790925560078054919093169116179055565b60408051336020808301919091528183018690528251808303840181526060830193849052805190820120601754631b23d15760e21b909452606483018181526084840187905260a48401859052608060c48501908152865160e486015286517329d2706cdb97783a652314863668ed5cab971db296636c8f455c9694958a9591948a9490939092610104019185019080838360005b838110156125ed5781810151838201526020016125d5565b50505050905090810190601f16801561261a5780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038186803b15801561263a57600080fd5b505af415801561264e573d6000803e3d6000fd5b505050506040513d602081101561266457600080fd5b50516126a9576040805162461bcd60e51b815260206004820152600f60248201526e2bb937b7339030b1b190383937b7b360891b604482015290519081900360640190fd5b336000908152601f60205260408120546126ca90859063ffffffff61475016565b90506126d6338261573c565b336000818152601f60209081526040808320889055600354815163a9059cbb60e01b815260048101959095526024850186905290516001600160a01b039091169363a9059cbb9360448083019493928390030190829087803b15801561273b57600080fd5b505af115801561274f573d6000803e3d6000fd5b505050506040513d602081101561276557600080fd5b505161277057600080fd5b50505050565b6000838152601a60205260408120600601546001600160a01b031633146127df576040805162461bcd60e51b8152602060048201526018602482015277496e76616c696420636f6e7472616374206164647265737360401b604482015290519081900360640190fd5b600354604080516323b872dd60e01b81526001600160a01b03858116600483015230602483015260448201879052915191909216916323b872dd9160648083019260209291908290030181600087803b15801561283b57600080fd5b505af115801561284f573d6000803e3d6000fd5b505050506040513d602081101561286557600080fd5b5051949350505050565b600a5481565b61287d612a68565b61288657600080fd5b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b60095481565b60185481565b601f6020526000908152604090205481565b6004546001600160a01b031681565b600b5481565b601d545b90565b60115481565b60235460ff1615612959576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b60238054600160ff1990911617905560008054610100600160a81b0319166101006001600160a01b038581169190910291909117909155600480546001600160a01b03199081168b8416179091556002805482168a8416179055600380548216898416179055600680548216888416179055600580548216878416179055600780549091169185169190911790556129f0816157bb565b5050612000600855505060016009819055610376600a90815569044664c7bf6451f00000600b55670de0b6b3a7640000600c819055600d55610400600e556064600f55600760105560128290556108006015556016556019805460ff1916909117905550505050565b6001546001600160a01b031690565b6001546001600160a01b0316331490565b60095490565b60005461010090046001600160a01b03163314612acd5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b612ad981600954614c9d565b50565b80612ae681614b16565b6000828152601a6020526040902060018101546006909101546001600160a01b03168015612b8857612b85816001600160a01b03166332ba2e536040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612b4c57600080fd5b505af1158015612b60573d6000803e3d6000fd5b505050506040513d6020811015612b7657600080fd5b5051839063ffffffff61473e16565b91505b61277084338461582a565b6002546001600160a01b031681565b612baa614c5c565b6000828152602080526040902060028101546001600160a01b031633811480612bda575083612bd83361152b565b145b612c155760405162461bcd60e51b8152600401808060200182810382526024815260200180615d256024913960400191505060405180910390fd5b600954601554600a54612c2f90829063ffffffff61473e16565b6001850154612c4590849063ffffffff61475016565b81612c4c57fe5b061015612ca0576040805162461bcd60e51b815260206004820181905260248201527f4e6f7420616c6c6f776564206265666f72652061756374696f6e506572696f64604482015290519081900360640190fd5b60028301546001600160a01b0316612cf1576040805162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b21030bab1ba34b7b760891b604482015290519081900360640190fd5b6000858152601a6020526040902080548454600690920154909182916001600160a01b03168015612d9457612d91816001600160a01b031663a446c2db6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d5857600080fd5b505afa158015612d6c573d6000803e3d6000fd5b505050506040513d6020811015612d8257600080fd5b5051849063ffffffff61473e16565b92505b818310158015612db357506000898152601a6020526040902060030154155b15612efe576003546040805163a9059cbb60e01b81526001600160a01b038981166004830152602482018690529151919092169163a9059cbb9160448083019260209291908290030181600087803b158015612e0e57600080fd5b505af1158015612e22573d6000803e3d6000fd5b505050506040513d6020811015612e3857600080fd5b5051612e7f576040805162461bcd60e51b8152602060048201526011602482015270109a59081c995d1d5c9b8819985a5b1959607a1b604482015290519081900360640190fd5b600187018590556005546040805163e12ab1af60e01b8152600481018c9052602481018c90526044810187905290516001600160a01b039092169163e12ab1af9160648082019260009290919082900301818387803b158015612ee157600080fd5b505af1158015612ef5573d6000803e3d6000fd5b50505050613039565b612f0a86896000614e67565b612f148986614c9d565b6002878101546003890180546040805160206101006001851615026000190190931695909504601f8101839004830286018301909152808552600094612fc1948c948994600160a01b90920460ff16939091830182828015612fb75780601f10612f8c57610100808354040283529160200191612fb7565b820191906000526020600020905b815481529060010190602001808311612f9a57829003601f168201915b5050505050615027565b6005546040805163e12ab1af60e01b815260048101849052602481018e90526044810187905290519293506001600160a01b039091169163e12ab1af9160648082019260009290919082900301818387803b15801561301f57600080fd5b505af1158015613033573d6000803e3d6000fd5b50505050505b60018088015460008b815260208052604081208181559283018190556002830180546001600160a81b03191690559091906130776003830182615c0d565b50506000998a52602080526040909920600101989098555050505050505050565b60225481565b60005461010090046001600160a01b031633146130ec5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b6005546016546040805163a3b1d8cb60e01b8152600481018590526024810192909252516001600160a01b039092169163a3b1d8cb9160448082019260009290919082900301818387803b15801561314357600080fd5b505af1158015613157573d6000803e3d6000fd5b50505050606481111561319b576040805162461bcd60e51b8152602060048201526007602482015266746f6f2062696760c81b604482015290519081900360640190fd5b601655565b60008113156131f95760195460ff166131f9576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b6000828152601a60205260409020600601546001600160a01b03163314613262576040805162461bcd60e51b8152602060048201526018602482015277496e76616c696420636f6e7472616374206164647265737360401b604482015290519081900360640190fd5b6124ae81600080614ba0565b60005461010090046001600160a01b031633146132bc5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b60008111613311576040805162461bcd60e51b815260206004820181905260248201527f426c6f636b7320696e74657276616c206d757374206265206e6f6e2d7a65726f604482015290519081900360640190fd5b600e55565b601c5490565b613324614c5c565b6000858152601a60205260409020805460039091015415801561334657508015155b613397576040805162461bcd60e51b815260206004820181905260248201527f496e76616c69642076616c696461746f7220666f7220616e2061756374696f6e604482015290519081900360640190fd5b336000818152601b60209081526040918290205460065483516370a0823160e01b81526004810195909552925190936001600160a01b03909316926370a08231926024808301939192829003018186803b1580156133f457600080fd5b505afa158015613408573d6000803e3d6000fd5b505050506040513d602081101561341e57600080fd5b505115801561342f57506000198114155b613477576040805162461bcd60e51b8152602060048201526014602482015273416c72656164792075736564206164647265737360601b604482015290519081900360640190fd5b60095460185480158061348a5750818111155b6134cd576040805162461bcd60e51b815260206004820152600f60248201526e10dbdbdb191bdddb881c195c9a5bd9608a1b604482015290519081900360640190fd5b601554600a546134e3908263ffffffff61473e16565b60008b8152601a602052604090206002015461350690859063ffffffff61475016565b8161350d57fe5b0610613559576040805162461bcd60e51b8152602060048201526016602482015275125b9d985b1a5908185d58dd1a5bdb881c195c9a5bd960521b604482015290519081900360640190fd5b6000898152601a602052604090206006015484906001600160a01b031680156135cf576135cc816001600160a01b031663a446c2db6040518163ffffffff1660e01b815260040160206040518083038186803b1580156135b857600080fd5b505afa158015612b60573d6000803e3d6000fd5b91505b60008b8152602080526040902080546135e8848261597c565b93508b8410613630576040805162461bcd60e51b815260206004820152600f60248201526e26bab9ba103134b2103434b3b432b960891b604482015290519081900360640190fd5b600354604080516323b872dd60e01b8152336004820152306024820152604481018f905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b15801561368a57600080fd5b505af115801561369e573d6000803e3d6000fd5b505050506040513d60208110156136b457600080fd5b5051613700576040805162461bcd60e51b8152602060048201526016602482015275151c985b9cd9995c88185b5bdd5b9d0819985a5b195960521b604482015290519081900360640190fd5b80156137d25760035460028301546040805163a9059cbb60e01b81526001600160a01b039283166004820152602481018590529051919092169163a9059cbb9160448083019260209291908290030181600087803b15801561376157600080fd5b505af1158015613775573d6000803e3d6000fd5b505050506040513d602081101561378b57600080fd5b50516137d2576040805162461bcd60e51b8152602060048201526011602482015270109a59081c995d1d5c9b8819985a5b1959607a1b604482015290519081900360640190fd5b8b8255600282018054336001600160a01b03199091161760ff60a01b1916600160a01b8d15150217905561380a600383018b8b615c51565b50600560009054906101000a90046001600160a01b03166001600160a01b0316630934a6df8e8a8f6040518463ffffffff1660e01b8152600401808481526020018381526020018281526020019350505050600060405180830381600087803b15801561387657600080fd5b505af115801561388a573d6000803e3d6000fd5b5050505050505050505050505050505050565b60005461010090046001600160a01b031633146138eb5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b6138f361598c565b565b60085490565b60005461010090046001600160a01b031633146139495760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b600c91909155600d55565b6000838152601a60205260408120600601546001600160a01b03163314806139f357506004805460408051631ab0168360e31b8152905133936001600160a01b039093169263d580b41892808201926020929091829003018186803b1580156139bc57600080fd5b505afa1580156139d0573d6000803e3d6000fd5b505050506040513d60208110156139e657600080fd5b50516001600160a01b0316145b613a3f576040805162461bcd60e51b8152602060048201526018602482015277496e76616c696420636f6e7472616374206164647265737360401b604482015290519081900360640190fd5b6003546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018790529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561283b57600080fd5b6007546001600160a01b031681565b60005461010090046001600160a01b03163314613af25760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b60008111613aff57600080fd5b600554600b5460408051632dbe9d3160e21b8152600481018590526024810192909252516001600160a01b039092169163b6fa74c49160448082019260009290919082900301818387803b158015613b5657600080fd5b505af1158015613b6a573d6000803e3d6000fd5b505050600b9190915550565b60145481565b60005460ff1681565b336000908152601b6020526040902054613b9e816118ea565b613be1576040805162461bcd60e51b815260206004820152600f60248201526e3737ba1030903b30b634b230ba37b960891b604482015290519081900360640190fd5b6000818152601a60205260409020600601546001600160a01b031680613c47576040805162461bcd60e51b815260206004820152601660248201527519195b1959d85d1a5bdb881b9bdd08195b98589b195960521b604482015290519081900360640190fd5b604080516303dd464160e51b8152841515600482015290516001600160a01b03831691637ba8c82091602480830192600092919082900301818387803b158015613c9057600080fd5b505af1158015613ca4573d6000803e3d6000fd5b50505050505050565b60216020526000908152604090205481565b80613cc981614b16565b6000828152601a60205260409020600301548015801590613cff5750600954600854613cfc90839063ffffffff61473e16565b11155b8015613d32575060036000848152601a6020526040902060060154600160a01b900460ff166003811115613d2f57fe5b14155b613d3b57600080fd5b6000838152601a6020526040812054601154909190613d60908363ffffffff61475016565b601181905560065460408051630852cd8d60e31b81526004810189905290519293506001600160a01b03909116916342966c689160248082019260009290919082900301818387803b158015613db557600080fd5b505af1158015613dc9573d6000803e3d6000fd5b5050506000868152601a6020818152604080842060058101546001600160a01b039081168652601b845282862060001990558b8652938352600601805460ff60a01b1916600360a01b179055600354815163a9059cbb60e01b81523360048201526024810189905291519316945063a9059cbb93604480830194928390030190829087803b158015613e5a57600080fd5b505af1158015613e6e573d6000803e3d6000fd5b505050506040513d6020811015613e8457600080fd5b5051613ecf576040805162461bcd60e51b8152602060048201526015602482015274151c985b9cd9995c881cdd185ad94819985a5b1959605a1b604482015290519081900360640190fd5b6005546040805163ae2e26b160e01b815233600482015260248101889052604481018590526064810184905290516001600160a01b039092169163ae2e26b19160848082019260009290919082900301818387803b15801561185357600080fd5b601c54601d5482565b60005461010090046001600160a01b03163314613f875760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b60008111613f9457600080fd5b600554600a5460408051635071805360e11b8152600481018590526024810192909252516001600160a01b039092169163a0e300a69160448082019260009290919082900301818387803b158015613feb57600080fd5b505af1158015613fff573d6000803e3d6000fd5b505050600a82905550600881905561401e81600463ffffffff61470616565b60158190556009546140359163ffffffff61473e16565b60185550565b614043612a68565b61404c57600080fd5b6001600160a01b03811661405f57600080fd5b6002546040516001600160a01b038084169216907f211c9015fc81c0dbd45bd99f0f29fc1c143bfd53442d5ffd722bbbef7a887fe990600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000908152601a602052604090205490565b6005546001600160a01b031681565b60005461010090046001600160a01b0316331461412a5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b6019805460ff1916911515919091179055565b614145612a68565b61414e57600080fd5b612ad9816157bb565b8161416181614b16565b600061416c83615998565b90506001600160a01b0381161580159061419c57506001600160a01b0381166000908152601b6020526040902054155b6141de576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b604482015290519081900360640190fd5b600954600f546000868152602160205260409020546142029163ffffffff61473e16565b811015614256576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636865636b706f696e74206e756d62657221000000000000604482015290519081900360640190fd5b6000858152601a602090815260408083206005908101549054915163b80fbce560e01b8152600481018a81526001600160a01b039283166024830181905288841660448401526080606484019081528b5160848501528b519197949095169563b80fbce5958d9589958c958f95909460a490920192918601918190849084905b838110156142ee5781810151838201526020016142d6565b50505050905090810190601f16801561431b5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b15801561433d57600080fd5b505af1158015614351573d6000803e3d6000fd5b5050506001600160a01b039182166000908152601b60209081526040808320600019905595909316808252858220899055978152601a835284812060050180546001600160a01b03191690981790975550602190529320929092555050565b60005461010090046001600160a01b031633146143fe5760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b306001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561444157600080fd5b505afa158015614455573d6000803e3d6000fd5b505050506040513d602081101561446b57600080fd5b50516001600160a01b0316146144b25760405162461bcd60e51b8152600401808060200182810382526026815260200180615d6f6026913960400191505060405180910390fd5b6000918252601a602052604090912060060180546001600160a01b0319166001600160a01b03909216919091179055565b60005461010090046001600160a01b031633146145315760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b600954614035908263ffffffff61473e16565b60005461010090046001600160a01b031633146145925760405162461bcd60e51b8152600401808060200182810382526026815260200180615d496026913960400191505060405180910390fd5b6138f36159ed565b6008831080156145aa5750600782115b6145ef576040805162461bcd60e51b815260206004820152601160248201527024b73b30b634b21036b4b3b930ba34b7b760791b604482015290519081900360640190fd5b6000838152601a6020526040808220600601548151636e7ce59160e01b81523360048201526024810185905291516001600160a01b0390911692636e7ce591926044808201939182900301818387803b15801561464b57600080fd5b505af115801561465f573d6000803e3d6000fd5b5050506000838152601a6020526040808220600601548151632830728d60e21b81523360048201526024810186905291516001600160a01b03909116935063a0c1ca349260448084019391929182900301818387803b158015613c9057600080fd5b600d5481565b6003546001600160a01b031681565b6000826146e557506000614700565b828202828482816146f257fe5b04146146fd57600080fd5b90505b92915050565b600080821161471457600080fd5b600082848161471f57fe5b04949350505050565b600081831061473757816146fd565b5090919050565b6000828201838110156146fd57600080fd5b60008282111561475f57600080fd5b50900390565b600954600061477b82600163ffffffff61473e16565b9050614785615ccf565b506000818152601e602090815260408083208151808301909252805480835260019091015492820183905290926147bc9290614ba0565b506000918252601e6020526040822082815560010191909155600955565b60008080805b84518167ffffffffffffffff161015614a5a57600073ad758ddd05c851abfe184d6b1be0a5f1b3bcab786377d32e94886148268967ffffffffffffffff871660416159fc565b6040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614878578181015183820152602001614860565b50505050905090810190601f1680156148a55780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b1580156148c357600080fd5b505af41580156148d7573d6000803e3d6000fd5b505050506040513d60208110156148ed57600080fd5b50516001600160a01b038082166000818152601b6020526040902054929350908516141561491c575050614a5a565b614925816118ea565b80156149425750836001600160a01b0316826001600160a01b0316115b15614a50576000818152601a60205260408120600681015493955085939091906001600160a01b03168015614a0257806001600160a01b031663b37f25908d8f61498b886140bb565b6040518463ffffffff1660e01b8152600401808481526020018381526020018281526020019350505050602060405180830381600087803b1580156149cf57600080fd5b505af11580156149e3573d6000803e3d6000fd5b505050506040513d60208110156149f957600080fd5b50519150614a3a565b82600001549150614a34614a238e61122f8f866146d690919063ffffffff16565b60018501549063ffffffff61473e16565b60018401555b614a4a888363ffffffff61473e16565b97505050505b50506041016147e0565b50614a79614a66613316565b600b5461122f908563ffffffff6146d616565b601354909650614a8f908763ffffffff61473e16565b601355614ac16001614ab5600361122f6002614aa9613316565b9063ffffffff6146d616565b9063ffffffff61473e16565b821015614b0b576040805162461bcd60e51b8152602060048201526013602482015272322f332b31206e6f6e2d6d616a6f726974792160681b604482015290519081900360640190fd5b509395945050505050565b600654604080516331a9108f60e11b815260048101849052905133926001600160a01b031691636352211e916024808301926020929190829003018186803b158015614b6157600080fd5b505afa158015614b75573d6000803e3d6000fd5b505050506040513d6020811015614b8b57600080fd5b50516001600160a01b031614612ad957600080fd5b80614c3a576000831315614bc957601c54614bc1908463ffffffff61473e16565b601c55614bed565b6000831215614bed57601c54614be990600085900363ffffffff61475016565b601c555b6000821315614c1157601d54614c09908363ffffffff61473e16565b601d55614c35565b6000821215614c3557601d54614c3190600084900363ffffffff61475016565b601d555b611dd3565b6000818152601e60205260409020805484018155600101805483019055505050565b60005460ff16156138f3576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b6000828152601a602052604081205490614cb68461244e565b6000858152601a6020526040812060038101869055600181015460069091015492935090916001600160a01b03168015614dae576000819050614d41816001600160a01b03166332ba2e536040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614d2d57600080fd5b505af1158015612d6c573d6000803e3d6000fd5b9250806001600160a01b031663753868e36040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614d7e57600080fd5b505af1158015614d92573d6000803e3d6000fd5b505050506040513d6020811015614da857600080fd5b50519350505b614db987858461582a565b6000600954871115614dcb5786614dce565b60005b9050614de284870160000360001983614ba0565b60055460408051635e04d48360e01b81526001600160a01b038881166004830152602482018c9052604482018b9052606482018a905291519190921691635e04d48391608480830192600092919082900301818387803b158015614e4557600080fd5b505af1158015614e59573d6000803e3d6000fd5b505050505050505050505050565b600d54821015614ebe576040805162461bcd60e51b815260206004820152601760248201527f4e6f7420656e6f756768206865696d64616c6c20666565000000000000000000604482015290519081900360640190fd5b6003546001600160a01b03166323b872dd3330614ee1868663ffffffff61473e16565b6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015614f4957600080fd5b505af1158015614f5d573d6000803e3d6000fd5b505050506040513d6020811015614f7357600080fd5b5051614fbc576040805162461bcd60e51b8152602060048201526013602482015272119959481d1c985b9cd9995c8819985a5b1959606a1b604482015290519081900360640190fd5b602254614fcf908363ffffffff61473e16565b6022556005546040805163a449d79560e01b81526001600160a01b038681166004830152602482018690529151919092169163a449d79591604480830192600092919082900301818387803b158015613c9057600080fd5b60008061503383615998565b90506001600160a01b0381161580159061506357506001600160a01b0381166000908152601b6020526040902054155b6150a5576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b604482015290519081900360640190fd5b6009546012546005546011546001600160a01b03909116906000906150d0908a63ffffffff61473e16565b9050806011819055506040518061010001604052808a8152602001600081526020018581526020016000815260200160008152602001866001600160a01b03168152602001896151215760006151ad565b600754600480546040805163d4ad267360e01b81529283018990526001600160a01b03888116602485015291821660448401525192169163d4ad2673916064808201926020929091908290030181600087803b15801561518057600080fd5b505af1158015615194573d6000803e3d6000fd5b505050506040513d60208110156151aa57600080fd5b50515b6001600160a01b03168152602001600190526000848152601a60209081526040918290208351815590830151600182015590820151600282015560608201516003808301919091556080830151600483015560a08301516005830180546001600160a01b039283166001600160a01b03199182161790915560c08501516006850180549190931691161780825560e08501519260ff60a01b1990911690600160a01b90849081111561525b57fe5b0217905550505060008381526021602052604080822086905560065481516340c10f1960e01b81526001600160a01b038e8116600483015260248201889052925192909116926340c10f199260448084019382900301818387803b1580156152c257600080fd5b505af11580156152d6573d6000803e3d6000fd5b5050506001600160a01b0386166000908152601b6020526040812085905561530391508a90600190614ba0565b836020600085815260200190815260200160002060010181905550816001600160a01b03166333a8383c868986888e876040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b0316815260200180602001868152602001858152602001848152602001838152602001828103825287818151815260200191508051906020019080838360005b838110156153af578181015183820152602001615397565b50505050905090810190601f1680156153dc5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561540057600080fd5b505af1158015615414573d6000803e3d6000fd5b5050505061542c60018461473e90919063ffffffff16565b601255509098975050505050505050565b615445615ccf565b506040805180820190915281518152602082810190820152919050565b606061546d82615a7b565b61547657600080fd5b600061548183615ab5565b90506060816040519080825280602002602001820160405280156154bf57816020015b6154ac615ccf565b8152602001906001900390816154a45790505b50905060006154d18560200151615b11565b60208601510190506000805b84811015615528576154ee83615b74565b915060405180604001604052808381526020018481525084828151811061551157fe5b6020908102919091010152918101916001016154dd565b509195945050505050565b80516000901580159061554857508151602110155b61555157600080fd5b60006155608360200151615b11565b8351602080860151830180519394509184900392919083101561558a57826020036101000a820491505b50949350505050565b80516000906001146155a457600080fd5b6020820151805160001a9081156155bc5760016155bf565b60005b949350505050565b6000828152601a602052604081206006015481906001600160a01b03161561566d576000848152601a6020908152604080832060060154815163753868e360e01b815291516001600160a01b039091169363753868e393600480850194919392918390030190829087803b15801561563e57600080fd5b505af1158015615652573d6000803e3d6000fd5b505050506040513d602081101561566857600080fd5b505190505b600954615680818563ffffffff61473e16565b6000868152601a602052604080822060048082019490945560068101805460ff60a01b1916600160a11b1790556005805491015482516381dc101b60e01b81529485018a9052602485018690526001600160a01b03908116604486015291519116926381dc101b92606480830193919282900301818387803b15801561570557600080fd5b505af1158015615719573d6000803e3d6000fd5b5050506000868152601a602052604090205461244591508363ffffffff61473e16565b60225461574f908263ffffffff61475016565b6022556005546040805163122b648160e01b81526001600160a01b038581166004830152602482018590529151919092169163122b648191604480830192600092919082900301818387803b1580156157a757600080fd5b505af115801561205a573d6000803e3d6000fd5b6001600160a01b0381166157ce57600080fd5b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b60145461583d908263ffffffff61473e16565b6014556000838152601a60209081526040808320600101839055600354815163a9059cbb60e01b81526001600160a01b038781166004830152602482018790529251929091169363a9059cbb9360448084019491939192918390030190829087803b1580156158ab57600080fd5b505af11580156158bf573d6000803e3d6000fd5b505050506040513d60208110156158d557600080fd5b505161591e576040805162461bcd60e51b8152602060048201526013602482015272496e737566666963656e74207265776172647360681b604482015290519081900360640190fd5b60055460145460408051635b42d93560e11b815260048101879052602481018590526044810192909252516001600160a01b039092169163b685b26a9160648082019260009290919082900301818387803b158015613c9057600080fd5b60008183101561473757816146fd565b6000805460ff19169055565b600081516040146159e1576040805162461bcd60e51b815260206004820152600e60248201526d496e76616c6964207075626b657960901b604482015290519081900360640190fd5b50805160209091012090565b6000805460ff19166001179055565b606081830184511015615a0e57600080fd5b606082158015615a295760405191506020820160405261558a565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015615a62578051835260209283019201615a4a565b5050858452601f01601f19166040525050949350505050565b8051600090615a8c575060006115b0565b6020820151805160001a9060c0821015615aab576000925050506115b0565b5060019392505050565b8051600090615ac6575060006115b0565b60008090506000615ada8460200151615b11565b602085015185519181019250015b80821015615b0857615af982615b74565b60019093019290910190615ae8565b50909392505050565b8051600090811a6080811015615b2b5760009150506115b0565b60b8811080615b46575060c08110801590615b46575060f881105b15615b555760019150506115b0565b60c0811015615b695760b5190190506115b0565b60f5190190506115b0565b80516000908190811a6080811015615b8f5760019150615c06565b60b8811015615ba457607e1981019150615c06565b60c0811015615bd15760b78103600185019450806020036101000a85510460018201810193505050615c06565b60f8811015615be65760be1981019150615c06565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b50805460018160011615610100020316600290046000825580601f10615c335750612ad9565b601f016020900490600052602060002090810190612ad99190615ce9565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615c925782800160ff19823516178555615cbf565b82800160010185558215615cbf579182015b82811115615cbf578235825591602001919060010190615ca4565b50615ccb929150615ce9565b5090565b604051806040016040528060008152602001600081525090565b61290791905b80821115615ccb5760008155600101615cef56fe56616c696461746f7220736574205468726573686f6c64206578636565646564214f6e6c7920626964646572206f722076616c696461746f722063616e20636f6e6669726d4f6e6c7920676f7665726e616e636520636f6e747261637420697320617574686f72697a65644f776e6572206f6620636f6e7472616374206d757374206265207374616b654d616e61676572a265627a7a723158205303fd765be1bd98f895304344671726e733bd897ca8b4c4e93a97b01f9a248864736f6c63430005110032
Deployed Bytecode Sourcemap
118328:31423:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;118328:31423:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;122182:248;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;122182:248:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;122182:248:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;122182:248: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;122182:248:0;;-1:-1:-1;122182:248:0;-1:-1:-1;122182:248:0;:::i;:::-;;138255:1483;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;138255:1483:0;;;;;;;;;;;;;-1:-1:-1;;;;;138255:1483:0;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;138255:1483:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;138255:1483: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;138255:1483:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;138255:1483:0;;-1:-1:-1;138255:1483:0;;-1:-1:-1;;;;;138255:1483:0:i;:::-;;;;;;;;;;;;;;;;135972:116;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135972:116:0;;:::i;116681:28::-;;;:::i;116603:27::-;;;:::i;116059:31::-;;;:::i;133354:139::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;133354:139:0;-1:-1:-1;;;;;133354:139:0;;:::i;133580:236::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;133580:236:0;;:::i;133186:134::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;133186:134:0;-1:-1:-1;;;;;133186:134:0;;:::i;143231:1009::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;143231:1009:0;;:::i;116796:31::-;;;:::i;128445:119::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;128445:119:0;;:::i;116406:38::-;;;:::i;117827:60::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;117827:60:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;137627:620;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137627:620:0;;:::i;:::-;;;;;;;;;;;;;;;;;;130803:1160;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;130803:1160:0;;;;;;;;;;;;;;:::i;127700:558::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;127700:558:0;;:::i;115980:29::-;;;:::i;:::-;;;;-1:-1:-1;;;;;115980:29:0;;;;;;;;;;;;;;116736:28;;;:::i;117644:47::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;117644:47:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;117644:47:0;-1:-1:-1;;;;;117644:47:0;;;;;;-1:-1:-1;;;;;117644:47:0;-1:-1:-1;;;;;117644:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;117734:52;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;117734:52:0;-1:-1:-1;;;;;117734:52:0;;:::i;116302:25::-;;;:::i;122438:262::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;122438:262:0;-1:-1:-1;;;;;122438:262:0;;:::i;116451:32::-;;;:::i;116492:33::-;;;:::i;129319:495::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;129319:495:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;129319:495:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;129319:495: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;129319:495:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;129319:495:0;;-1:-1:-1;129319:495:0;;-1:-1:-1;;;;;129319:495:0:i;117989:51::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;117989:51:0;;:::i;:::-;;;;;;;;;;;;;;;-1:-1:-1;;;;;117989:51:0;-1:-1:-1;;;;;117989: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;117989:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;116948:29;;;:::i;116571:25::-;;;:::i;137473:146::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137473:146:0;;:::i;26600:29::-;;;:::i;141574:1649::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;141574:1649:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;141574:1649:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;141574:1649: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;141574:1649:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;141574:1649:0;;-1:-1:-1;141574:1649:0;;-1:-1:-1;;;;;141574:1649:0:i;120506:118::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;120506:118:0;;:::i;120360:138::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;120360:138:0;;;;;;;;:::i;148998:328::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;148998:328:0;;;;;;;;;;;;;;;;;;;:::i;121561:613::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;121561:613:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;121561:613:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;121561:613: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;121561:613:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;121561:613:0;;-1:-1:-1;121561:613:0;;-1:-1:-1;;;;;121561:613:0:i;128991:320::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;128991:320:0;;;;;;;;;;;-1:-1:-1;;;;;128991:320:0;;:::i;116185:22::-;;;:::i;5306:140::-;;;:::i;116112:27::-;;;:::i;116907:34::-;;;:::i;117896:46::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;117896:46:0;-1:-1:-1;;;;;117896:46:0;;:::i;115918:23::-;;;:::i;116238:32::-;;;:::i;137222:117::-;;;:::i;116538:26::-;;;:::i;118971:1234::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;118971:1234:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;4516:79::-;;;:::i;4851:92::-;;;:::i;120632:85::-;;;:::i;128316:121::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;128316:121:0;;:::i;132355:427::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;132355:427:0;;:::i;27894:24::-;;;:::i;125554:2138::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;125554:2138:0;;;;;;;:::i;118162:31::-;;;:::i;135709:255::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135709:255:0;;:::i;134734:375::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;134734:375:0;;;;;;;:::i;133824:197::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;133824:197:0;;:::i;137347:118::-;;;:::i;122708:2838::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;122708:2838:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;122708:2838:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;122708:2838: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;122708:2838:0;;-1:-1:-1;122708:2838:0;-1:-1:-1;122708:2838:0;:::i;27656:73::-;;;:::i;120725:99::-;;;:::i;136096:180::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;136096:180:0;;;;;;;:::i;128572:411::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;128572:411:0;;;;;;;;;;;-1:-1:-1;;;;;128572:411:0;;:::i;116016:36::-;;;:::i;134071:217::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;134071:217:0;;:::i;116637:37::-;;;:::i;27027:18::-;;;:::i;149334:414::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;149334:414:0;;;;:::i;118095:58::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;118095:58:0;;:::i;129822:937::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;129822:937:0;;:::i;117793:27::-;;;:::i;135117:383::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135117:383:0;;:::i;28374:210::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;28374:210:0;-1:-1:-1;;;;;28374:210:0;;:::i;120832:131::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;120832:131:0;;:::i;115948:25::-;;;:::i;120213:112::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;120213:112:0;;;;:::i;5623:109::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5623:109:0;-1:-1:-1;;;;;5623:109:0;;:::i;136284:930::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;136284:930:0;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;136284:930:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;136284:930: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;136284:930:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;136284:930:0;;-1:-1:-1;136284:930:0;;-1:-1:-1;;;;;136284:930:0:i;134423:303::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;134423:303:0;;;;;;-1:-1:-1;;;;;134423:303:0;;:::i;135558:143::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135558:143:0;;:::i;27579:69::-;;;:::i;132790:388::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;132790:388:0;;;;;;;;;;;;:::i;116352:29::-;;;:::i;115892:19::-;;;:::i;122182:248::-;122349:73;122358:10;122370:6;122378:11;122391:16;122409:12;;122349:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;122349:8:0;;-1:-1:-1;;;122349:73:0:i;:::-;122182:248;;;;;:::o;138255:1483::-;28198:9;;138459:7;;-1:-1:-1;;;;;28198:9:0;28184:10;:23;28176:32;;;;;;138851:14;138868:65;138909:23;;138868:36;138886:17;;138868:13;:17;;:36;;;;:::i;:::-;:40;:65;:40;:65;:::i;:::-;138851:82;;138953:35;138962:17;;138981:6;138953:8;:35::i;:::-;138944:44;;139001:22;139026:34;139056:3;139026:25;139037:13;;139026:6;:10;;:25;;;;:::i;:34::-;-1:-1:-1;;;;;139112:27:0;;;139071;139112;;;:17;:27;;;;;;;;;139101:39;;:10;:39;;;;;139155:25;;;;139001:59;;-1:-1:-1;139101:39:0;139155:25;:41;139151:255;;139229:25;;;;139289:16;;139213:93;;;-1:-1:-1;;;139213:93:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;139229:25:0;;;;139213:59;;:93;;;;;139229:25;;139213:93;;;;;;;;139229:25;;139213:93;;;5:2:-1;;;;30:1;27;20:12;5:2;139213:93:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;139213:93:0;;;;139151:255;;;139358:16;;;;:36;;139379:14;139358:36;:20;:36;:::i;:::-;139339:16;;;:55;139151:255;139427:26;:6;139438:14;139427:26;:10;:26;:::i;:::-;139418:35;;139464:18;139485:31;:29;:31::i;:::-;139606:16;:28;;;139464:52;-1:-1:-1;139645:17:0;:15;:17::i;:::-;139680:50;139695:10;139707:6;139715:8;139725:4;139680:14;:50::i;:::-;139673:57;138255:1483;-1:-1:-1;;;;;;;;;;138255:1483:0:o;135972:116::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136054:17;:26;135972:116::o;116681:28::-;;;;:::o;116603:27::-;;;;:::o;116059:31::-;;;;:::o;133354:139::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;133429:22:0;;133421:31;;;;;;133463:5;:22;;-1:-1:-1;;;;;;133463:22:0;-1:-1:-1;;;;;133463:22:0;;;;;;;;;;133354:139::o;133580:236::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;133692:1;133677:12;:16;133669:25;;;;;;133705:6;;133745:18;;133705:59;;;-1:-1:-1;;;133705:59:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;133705:6:0;;;;:25;;:59;;;;;:6;;:59;;;;;;;;:6;;:59;;;5:2:-1;;;;30:1;27;20:12;5:2;133705:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;133775:18:0;:33;;;;-1:-1:-1;133580:236:0:o;133186:134::-;133272:11;;:40;;;-1:-1:-1;;;133272:40:0;;-1:-1:-1;;;;;133272:40:0;;;;;;;133245:7;133272:40;;;;;;;;133245:7;;133272:11;;:31;;:40;;;;;;;;;;;;;;;:11;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;133272:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;133272:40:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;133272:40:0;;-1:-1:-1;133186:134:0;;;;:::o;143231:1009::-;143286:11;118706:30;118724:11;118706:17;:30::i;:::-;143352:13;143318:23;;;;:10;:23;;;;;:30;;;-1:-1:-1;;;143318:30:0;;;;:47;;;;;;;;;143310:83;;;;;-1:-1:-1;;;143310:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;143412:23;;;;:10;:23;;;;;:41;;;:46;143404:86;;;;;-1:-1:-1;;;143404:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;143527:12;;143503:21;143558:23;;;:10;:23;;;;;:32;;;:49;-1:-1:-1;143558:49:0;143550:84;;;;;-1:-1:-1;;;143550:84:0;;;;;;;;;;;;-1:-1:-1;;;143550:84:0;;;;;;;;;;;;;;;143647:14;143664:23;;;:10;:23;;;;;:30;143723:10;;143713:20;;;143705:29;;;;;;143747:24;143790:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;143790:39:0;:55;143786:180;;143897:23;;;;:10;:23;;;;;;;;:39;;;143881:73;;-1:-1:-1;;;143881:73:0;;;;-1:-1:-1;;;;;143897:39:0;;;;143881:71;;:73;;;;;143897:23;;143881:73;;;;;;;;;143897:39;143881:73;;;5:2:-1;;;;30:1;27;20:12;5:2;143881:73:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;143881:73:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;143881:73:0;;-1:-1:-1;143786:180:0;144041:58;144063:28;:6;144074:16;144063:28;:10;:28;:::i;:::-;144094:1;144097;144041:14;:58::i;:::-;144112:23;;;;:10;:23;;;;;;:30;;;:46;;-1:-1:-1;;;;144112:46:0;-1:-1:-1;;;144112:46:0;;;144169:6;;;144201:30;;;144169:63;;-1:-1:-1;;;144169:63:0;;;;;;;;-1:-1:-1;;;;;144201:30:0;;;144169:63;;;;;;:6;;;:18;;:63;;;;;;;;;;;144112:23;144169:6;:63;;;5:2:-1;;;;30:1;27;20:12;5:2;144169:63:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;144169:63:0;;;;118747:1;;;143231:1009;;:::o;116796:31::-;;;;:::o;128445:119::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;128528:12;:28;128445:119::o;116406:38::-;;;;:::o;117827:60::-;;;;;;;;;;;;;;;;;;;:::o;137627:620::-;137690:4;137733:23;;;:10;:23;;;;;:39;;;;137811:41;;;;137880:30;;137937;;;;;138002:12;;137733:39;;137811:41;;-1:-1:-1;;;137937:30:0;;;;;;138035:10;;;;;:85;;-1:-1:-1;138063:20:0;;;;;:56;;;138106:13;138087:15;:32;;138063:56;138035:163;;;;-1:-1:-1;138138:22:0;;;:59;;;138184:13;138164:17;:33;138138:59;138035:203;;;;-1:-1:-1;138225:13:0;138215:6;:23;;;;;;;;;138035:203;138027:212;137627:620;-1:-1:-1;;;;;;;137627:620:0:o;130803:1160::-;27093:17;:15;:17::i;:::-;130945:11;118706:30;118724:11;118706:17;:30::i;:::-;130977:23;;;;:10;:23;;;;;:41;;;:46;130969:78;;;;;-1:-1:-1;;;130969:78:0;;;;;;;;;;;;-1:-1:-1;;;130969:78:0;;;;;;;;;;;;;;;131064:10;;131060:130;;131099:5;;:53;;;-1:-1:-1;;;131099:53:0;;131118:10;131099:53;;;;131138:4;131099:53;;;;;;;;;;;;-1:-1:-1;;;;;131099:5:0;;;;:18;;:53;;;;;;;;;;;;;;;:5;;:53;;;5:2:-1;;;;30:1;27;20:12;5:2;131099:53:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;131099:53:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;131099:53:0;131091:87;;;;;-1:-1:-1;;;131091:87:0;;;;;;;;;;;;-1:-1:-1;;;131091:87:0;;;;;;;;;;;;;;;131206:12;131202:382;;;131255:23;;;;:10;:23;;;;;:30;;;131244:42;;:6;;:42;:10;:42;:::i;:::-;131301:20;131324:23;;;:10;:23;;;;;:39;;;131235:51;;-1:-1:-1;;;;;;131324:39:0;131382:28;;131378:146;;131440:68;131467:12;-1:-1:-1;;;;;131451:54:0;;:56;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;131451:56:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;131451:56:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;131451:56:0;131440:6;;:68;:10;:68;:::i;:::-;131431:77;;131378:146;-1:-1:-1;131571:1:0;131538:23;;;:10;:23;;;;;:30;;:34;131202:382;131621:11;;131596:22;;131621:23;;131637:6;131621:23;:15;:23;:::i;:::-;131655:11;:28;;;131727:23;;;;:10;:23;;;;;:30;131596:48;;-1:-1:-1;131727:42:0;;131762:6;131727:42;:34;:42;:::i;:::-;131694:23;;;;:10;:23;;;;;:75;;;;131782:36;;131804:6;;131694:23;131782:14;:36::i;:::-;131831:6;;:34;;;-1:-1:-1;;;131831:34:0;;;;;;;;;;-1:-1:-1;;;;;131831:6:0;;;;:21;;:34;;;;;:6;;:34;;;;;;;;:6;;:34;;;5:2:-1;;;;30:1;27;20:12;5:2;131831:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;131876:6:0;;;131908:23;;;:10;:23;;;;;;:30;131876:79;;-1:-1:-1;;;131876:79:0;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;131876:6:0;;;;-1:-1:-1;131876:18:0;;-1:-1:-1;131876:79:0;;;;;;;;;;;:6;;:79;;;5:2:-1;;;;30:1;27;20:12;127700:558:0;127758:11;118706:30;118724:11;118706:17;:30::i;:::-;127790:29;;;;:16;:29;;;;;:36;:41;127782:81;;;;;-1:-1:-1;;;127782:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;127938:1;127896:23;;;:10;:23;;;;;:39;;;:43;;;;:110;;-1:-1:-1;127960:23:0;;;;:10;:23;;;;;:41;;;:46;127896:110;:231;;;;-1:-1:-1;128062:13:0;128028:23;;;;:10;:23;;;;;:30;;;-1:-1:-1;;;128028:30:0;;;;:47;;;;;;;;;:98;;;-1:-1:-1;128113:13:0;128079:23;;;;:10;:23;;;;;:30;;;-1:-1:-1;;;128079:30:0;;;;:47;;;;;;;;;128028:98;127874:264;;;;;;128171:12;;128151:17;;128171:19;;128188:1;128171:19;:16;:19;:::i;:::-;128151:39;;128218:32;128227:11;128240:9;128218:8;:32::i;:::-;118747:1;127700:558;;:::o;115980:29::-;;;-1:-1:-1;;;;;115980:29:0;;:::o;116736:28::-;;;;:::o;117644:47::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;117644:47:0;;;;;;;;-1:-1:-1;;;117644:47:0;;;;;:::o;117734:52::-;;;;;;;;;;;;;:::o;116302:25::-;;;;:::o;122438:262::-;122499:7;-1:-1:-1;;;;;122523:20:0;;;;:56;;-1:-1:-1;122547:11:0;;:27;;;-1:-1:-1;;;122547:27:0;;-1:-1:-1;;;;;122547:27:0;;;;;;;;;:11;;;;;:21;;:27;;;;;;;;;;;;;;:11;:27;;;5:2:-1;;;;30:1;27;20:12;5:2;122547:27:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;122547:27:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;122547:27:0;:32;122523:56;122519:97;;;-1:-1:-1;122603:1:0;122596:8;;122519:97;122644:11;;:40;;;-1:-1:-1;;;122644:40:0;;-1:-1:-1;;;;;122644:40:0;;;;;;;122633:52;122644:40;;;;;;;;122633:10;;122644:11;;;;;:31;;:40;;;;;;;;;;;;;;:11;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;122644:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;122644:40:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;122644:40:0;122633:52;;122644:40;122633:52;;;;;;;;-1:-1:-1;122633:52:0;:59;;122438:262;-1:-1:-1;;122438:262:0:o;116451:32::-;;;;:::o;116492:33::-;;;;:::o;129319:495::-;27093:17;:15;:17::i;:::-;129561:18;;129533:25;:23;:25::i;:::-;:46;129525:92;;;;-1:-1:-1;;;129525:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;129645:10;;129636:6;:19;129628:57;;;;;-1:-1:-1;;;129628:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;129696:44;129714:4;129720:11;129733:6;129696:17;:44::i;:::-;129751:55;129761:4;129767:6;129775:16;129793:12;129751:9;:55::i;:::-;;129319:495;;;;;:::o;117989:51::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;117989:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;117989:51:0;;;-1:-1:-1;;;117989:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;116948:29::-;;;;;;:::o;116571:25::-;;;;:::o;137473:146::-;137545:7;137572:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;137572:39:0;;137473:146::o;26600:29::-;;;;;;-1:-1:-1;;;;;26600:29:0;;:::o;141574:1649::-;141674:8;;;141665:46;;;-1:-1:-1;;;141665:46:0;;;;141637:7;;141715:10;;-1:-1:-1;;;;;141674:8:0;;141665:44;;:46;;;;;;;;;;;141674:8;141665:46;;;5:2:-1;;;;30:1;27;20:12;5:2;141665:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;141665:46:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;141665:46:0;-1:-1:-1;;;;;141665:60:0;;141657:105;;;;;-1:-1:-1;;;141657:105:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;141773:43;141819:38;:29;:17;:27;:29::i;:::-;:36;:38::i;:::-;141773:84;-1:-1:-1;141868:16:0;;;;141964:1112;141988:16;:23;141984:1;:27;141964:1112;;;142033:36;142072:28;:16;142089:1;142072:19;;;;;;;;;;;;;;:26;:28::i;:::-;142033:67;;142115:19;142137:21;:9;142147:1;142137:12;;;;;;;;;;;;;;:19;:21::i;:::-;142115:43;;142173:15;142191:21;:9;142201:1;142191:12;;;;;;;:21;142173:39;-1:-1:-1;142241:24:0;:11;142173:39;142241:24;:15;:24;:::i;:::-;142337:3;142286:23;;;:10;:23;;;;;:39;;;142227:38;;-1:-1:-1;;;;;;142286:39:0;:55;142282:345;;142362:24;142405:23;;;:10;:23;;;;;;;;:39;;;;142474:30;;142389:164;;-1:-1:-1;;;142389:164:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;142405:39:0;;;;142389:62;;:164;;;;;;;;;;;142362:24;142405:39;142389:164;;;5:2:-1;;;;30:1;27;20:12;5:2;142389:164:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;142389:164:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;142389:164:0;;-1:-1:-1;142582:29:0;:7;142389:164;142582:29;:11;:29;:::i;:::-;142572:39;;142282:345;;142643:29;142675:23;;;:10;:23;;;;;:30;:43;;142710:7;142675:43;:34;:43;:::i;:::-;142733:23;;;;:10;:23;;;;;:54;;;142643:75;-1:-1:-1;142808:26:0;142804:261;;142855:35;142864:11;142877:12;;142855:8;:35::i;:::-;142804:261;;;142920:24;:9;142930:1;142920:12;;;;;;;;;;;;;;:22;:24::i;:::-;142916:149;;;142980:39;142997:21;143003:11;143016:1;142997:5;:21::i;:::-;142980:12;;:39;:16;:39;:::i;:::-;143038:11;;;;;142965:54;-1:-1:-1;142916:149:0;-1:-1:-1;;142013:3:0;;;;;-1:-1:-1;141964:1112:0;;-1:-1:-1;141964:1112:0;;-1:-1:-1;143115:69:0;143138:29;:11;143154:12;143138:29;:15;:29;:::i;:::-;143130:38;;143171:9;143170:10;;143182:1;143115:14;:69::i;:::-;143204:11;141574:1649;-1:-1:-1;;;;;141574:1649:0:o;120506:118::-;120588:11;;:28;;;-1:-1:-1;;;120588:28:0;;;;;;;;;;120561:7;;-1:-1:-1;;;;;120588:11:0;;:19;;:28;;;;;;;;;;;;;;:11;:28;;;5:2:-1;;;;30:1;27;20:12;120360:138:0;27093:17;:15;:17::i;:::-;120451:39;120469:4;120475:11;120488:1;120451:17;:39::i;:::-;120360:138;;:::o;148998:328::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;149167:11;:38;;-1:-1:-1;;;;;149167:38:0;;;-1:-1:-1;;;;;;149167:38:0;;;;;;;149216:6;:36;;;;;;;;;;;;;;;149263:7;:55;;;;;;;;;;;148998:328::o;121561:613::-;121796:38;;;121807:10;121796:38;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;121796:38:0;;;;;;;121786:49;;;;;;121859:16;;-1:-1:-1;;;121786:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:65;;;;:49;;121852:5;;121859:16;;121877:5;;121786: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;121786:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;121786:97:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;121786:97:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;121786:97:0;121764:162;;;;;-1:-1:-1;;;121764:162:0;;;;;;;;;;;;-1:-1:-1;;;121764:162:0;;;;;;;;;;;;;;;121993:10;121937:22;121981:23;;;:11;:23;;;;;;121962:43;;:14;;:43;:18;:43;:::i;:::-;121937:68;;122016:37;122026:10;122038:14;122016:9;:37::i;:::-;122076:10;122064:23;;;;:11;:23;;;;;;;;:40;;;122123:5;;:42;;-1:-1:-1;;;122123:42:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;122123:5:0;;;;:14;;:42;;;;;122064:23;122123:42;;;;;;;;:5;:42;;;5:2:-1;;;;30:1;27;20:12;5:2;122123:42:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;122123:42:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;122123:42:0;122115:51;;;;;;121561:613;;;;:::o;128991:320::-;129126:4;129151:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;129151:39:0;129194:10;129151:53;129143:90;;;;;-1:-1:-1;;;129143:90:0;;;;;;;;;;;;-1:-1:-1;;;129143:90:0;;;;;;;;;;;;;;;129251:5;;:52;;;-1:-1:-1;;;129251:52:0;;-1:-1:-1;;;;;129251:52:0;;;;;;;129289:4;129251:52;;;;;;;;;;;;:5;;;;;:18;;:52;;;;;;;;;;;;;;:5;;:52;;;5:2:-1;;;;30:1;27;20:12;5:2;129251:52:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;129251:52:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;129251:52:0;;128991:320;-1:-1:-1;;;;128991:320:0:o;116185:22::-;;;;:::o;5306:140::-;4728:9;:7;:9::i;:::-;4720:18;;;;;;5389:6;;5368:40;;5405:1;;-1:-1:-1;;;;;5389:6:0;;5368:40;;5405:1;;5368:40;5419:6;:19;;-1:-1:-1;;;;;;5419:19:0;;;5306:140::o;116112:27::-;;;;:::o;116907:34::-;;;;:::o;117896:46::-;;;;;;;;;;;;;:::o;115918:23::-;;;-1:-1:-1;;;;;115918:23:0;;:::o;116238:32::-;;;;:::o;137222:117::-;137305:26;;137222:117;;:::o;116538:26::-;;;;:::o;118971:1234::-;100090:6;;;;100089:7;100081:34;;;;;-1:-1:-1;;;100081:34:0;;;;;;;;;;;;-1:-1:-1;;;100081:34:0;;;;;;;;;;;;;;;100126:6;:13;;100135:4;-1:-1:-1;;100126:13:0;;;;;;-1:-1:-1;119272:37:0;;-1:-1:-1;;;;;;119272:37:0;100126:13;-1:-1:-1;;;;;119272:37:0;;;;;;;;;;;;;;119320:8;:20;;-1:-1:-1;;;;;;119320:20:0;;;;;;;;;;119351:9;:22;;;;;;;;;;119384:5;:22;;;;;;;;;;119417:11;:38;;;;;;;;;;119466:6;:36;;;;;;;;;;119513:7;:55;;;;;;;;;;;;;;119579:26;119598:6;119579:18;:26::i;:::-;-1:-1:-1;;119638:5:0;119618:16;:26;-1:-1:-1;;119685:1:0;119670:12;:16;;;119707:3;119697:7;:13;;;119764:16;119744:17;:36;119830:6;119816:10;:21;;;119866:14;:25;119946:4;119920:23;:30;119981:3;119961:17;:23;120018:1;119997:18;:22;120036:10;:14;;;120077:11;120061:13;:27;120119:13;:18;120173:17;:24;;-1:-1:-1;;120173:24:0;;;;;;-1:-1:-1;;;;118971:1234:0:o;4516:79::-;4581:6;;-1:-1:-1;;;;;4581:6:0;4516:79;:::o;4851:92::-;4929:6;;-1:-1:-1;;;;;4929:6:0;4915:10;:20;;4851:92::o;120632:85::-;120697:12;;120632:85;:::o;128316:121::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;128394:35;128403:11;128416:12;;128394:8;:35::i;:::-;128316:121;:::o;132355:427::-;132419:11;118706:30;118724:11;118706:17;:30::i;:::-;132443:14;132460:23;;;:10;:23;;;;;:30;;;;132524:39;;;;;-1:-1:-1;;;;;132524:39:0;132578:28;;132574:138;;132632:68;132659:12;-1:-1:-1;;;;;132643:54:0;;:56;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;132643:56:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;132643:56:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;132643:56:0;132632:6;;:68;:10;:68;:::i;:::-;132623:77;;132574:138;132724:50;132742:11;132755:10;132767:6;132724:17;:50::i;27894:24::-;;;-1:-1:-1;;;;;27894:24:0;;:::o;125554:2138::-;27093:17;:15;:17::i;:::-;125710:23;125736:29;;;:16;:29;;;;;125798:12;;;;-1:-1:-1;;;;;125798:12:0;125845:10;:25;;;:70;;;125904:11;125874:26;125889:10;125874:14;:26::i;:::-;:41;125845:70;125823:156;;;;-1:-1:-1;;;125823:156:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;126016:12;;126131:13;;126119:7;;126101:26;;126131:13;;126101:26;:17;:26;:::i;:::-;126079:18;;;;126061:37;;:13;;:37;:17;:37;:::i;:::-;:66;;;;;;:83;;126039:165;;;;;-1:-1:-1;;;126039:165:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;126223:12;;;;-1:-1:-1;;;;;126223:12:0;126215:56;;;;;-1:-1:-1;;;126215:56:0;;;;;;;;;;;;-1:-1:-1;;;126215:56:0;;;;;;;;;;;;;;;126284:23;126310;;;:10;:23;;;;;:30;;126426:14;;126474:39;;;;;126310:30;;;;-1:-1:-1;;;;;126474:39:0;126530:28;;126526:145;;126592:67;126627:12;-1:-1:-1;;;;;126611:45:0;;:47;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;126611:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;126611:47:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;126611:47:0;126592:14;;:67;:18;:67;:::i;:::-;126575:84;;126526:145;126745:13;126727:14;:31;;:81;;;;-1:-1:-1;126762:23:0;;;;:10;:23;;;;;:41;;;:46;126727:81;126723:801;;;126833:5;;:42;;;-1:-1:-1;;;126833:42:0;;-1:-1:-1;;;;;126833:42:0;;;;;;;;;;;;;;;:5;;;;;:14;;:42;;;;;;;;;;;;;;:5;;:42;;;5:2:-1;;;;30:1;27;20:12;5:2;126833:42:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;126833:42:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;126833:42:0;126825:72;;;;;-1:-1:-1;;;126825:72:0;;;;;;;;;;;;-1:-1:-1;;;126825:72:0;;;;;;;;;;;;;;;126948:18;;;:34;;;126997:6;;:67;;;-1:-1:-1;;;126997:67:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;126997:6:0;;;;:24;;:67;;;;;:6;;:67;;;;;;;;:6;;:67;;;5:2:-1;;;;30:1;27;20:12;5:2;126997:67:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;126997:67:0;;;;126723:801;;;127122:46;127140:11;127153;127166:1;127122:17;:46::i;:::-;127183:36;127192:11;127205:13;127183:8;:36::i;:::-;127351:24;;;;;127394:20;;;127261:168;;;;;;127351:24;127261:168;;;;;-1:-1:-1;;127261:168:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;127261:168:0;;127289:11;;127319:13;;-1:-1:-1;;;127351:24:0;;;;;;127394:20;;127261:168;;127394:20;127261:168;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:9;:168::i;:::-;127444:6;;:68;;;-1:-1:-1;;;127444:68:0;;;;;;;;;;;;;;;;;;;;;;127236:193;;-1:-1:-1;;;;;;127444:6:0;;;;:24;;:68;;;;;:6;;:68;;;;;;;;:6;;:68;;;5:2:-1;;;;30:1;27;20:12;5:2;127444:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;127444:68:0;;;;126723:801;;127555:18;;;;;127534;127591:29;;;:16;:29;;;;;127584:36;;;;;;;;;;;;;;-1:-1:-1;;;;;;127584:36:0;;;127555:18;;127591:29;127584:36;;;;127534:18;127584:36;:::i;:::-;-1:-1:-1;;127631:29:0;;;;:16;:29;;;;;;:40;;:53;;;;-1:-1:-1;;;;;;;;125554:2138:0:o;118162:31::-;;;;:::o;135709:255::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135797:6;;135845:13;;135797:62;;;-1:-1:-1;;;135797:62:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;135797:6:0;;;;:29;;:62;;;;;:6;;:62;;;;;;;;:6;;:62;;;5:2:-1;;;;30:1;27;20:12;5:2;135797:62:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;135797:62:0;;;;135898:3;135878:16;:23;;135870:43;;;;;-1:-1:-1;;;135870:43:0;;;;;;;;;;;;-1:-1:-1;;;135870:43:0;;;;;;;;;;;;;;;135924:13;:32;135709:255::o;134734:375::-;134831:1;134822:6;:10;134818:142;;;134904:17;;;;134896:52;;;;;-1:-1:-1;;;134896:52:0;;;;;;;;;;;;-1:-1:-1;;;134896:52:0;;;;;;;;;;;;;;;134980:23;;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;134980:39:0;135023:10;134980:53;134972:90;;;;;-1:-1:-1;;;134972:90:0;;;;;;;;;;;;-1:-1:-1;;;134972:90:0;;;;;;;;;;;;;;;135073:28;135088:6;135096:1;135099;135073:14;:28::i;133824:197::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;133931:1;133921:7;:11;133913:56;;;;;-1:-1:-1;;;133913:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;133980:23;:33;133824:197::o;137347:118::-;137436:14;:21;137347:118;:::o;122708:2838::-;27093:17;:15;:17::i;:::-;122901:30;122934:23;;;:10;:23;;;;;:30;;122999:41;;;;;:46;:77;;;;-1:-1:-1;123049:27:0;;;122999:77;122977:159;;;;;-1:-1:-1;;;122977:159:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123193:10;123147:25;123175:29;;;:17;:29;;;;;;;;;;123291:11;;:33;;-1:-1:-1;;;123291:33:0;;;;;;;;;;;123175:29;;-1:-1:-1;;;;;123291:11:0;;;;:21;;:33;;;;;123175:29;;123291:33;;;;;:11;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;123291:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;123291:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;123291:33:0;:38;:135;;;;;-1:-1:-1;;123383:17:0;:43;;123291:135;123269:205;;;;;-1:-1:-1;;;123269:205:0;;;;;;;;;;;;-1:-1:-1;;;123269:205:0;;;;;;;;;;;;;;;123511:12;;123565:19;;123680:25;;;:66;;;123733:13;123709:20;:37;;123680:66;123672:94;;;;;-1:-1:-1;;;123672:94:0;;;;;;;;;;;;-1:-1:-1;;;123672:94:0;;;;;;;;;;;;;;;124364:13;;124334:7;;:26;;124364:13;124334:26;:11;:26;:::i;:::-;124291:23;;;;:10;:23;;;;;:39;;;124273:58;;:13;;:58;:17;:58;:::i;:::-;:87;;;;;;124272:105;124250:177;;;;;-1:-1:-1;;;124250:177:0;;;;;;;;;;;;-1:-1:-1;;;124250:177:0;;;;;;;;;;;;;;;124440:22;124518:23;;;:10;:23;;;;;:39;;;124465:22;;-1:-1:-1;;;;;124518:39:0;124574:25;;124570:139;;124633:64;124668:9;-1:-1:-1;;;;;124652:42:0;;:44;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;124652:44:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;124633:64:0;124616:81;;124570:139;124721:23;124747:29;;;:16;:29;;;;;124818:14;;124862:46;124871:14;124818;124862:8;:46::i;:::-;124845:63;;124946:6;124929:14;:23;124921:51;;;;;-1:-1:-1;;;124921:51:0;;;;;;;;;;;;-1:-1:-1;;;124921:51:0;;;;;;;;;;;;;;;124991:5;;:53;;;-1:-1:-1;;;124991:53:0;;125010:10;124991:53;;;;125030:4;124991:53;;;;;;;;;;;;-1:-1:-1;;;;;124991:5:0;;;;:18;;:53;;;;;;;;;;;;;;;:5;;:53;;;5:2:-1;;;;30:1;27;20:12;5:2;124991:53:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;124991:53:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;124991:53:0;124983:88;;;;;-1:-1:-1;;;124983:88:0;;;;;;;;;;;;-1:-1:-1;;;124983:88:0;;;;;;;;;;;;;;;125120:25;;125116:138;;125170:5;;125185:12;;;;125170:50;;;-1:-1:-1;;;125170:50:0;;-1:-1:-1;;;;;125185:12:0;;;125170:50;;;;;;;;;;;;:5;;;;;:14;;:50;;;;;;;;;;;;;;:5;;:50;;;5:2:-1;;;;30:1;27;20:12;5:2;125170:50:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;125170:50:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;125170:50:0;125162:80;;;;;-1:-1:-1;;;125162:80:0;;;;;;;;;;;;-1:-1:-1;;;125162:80:0;;;;;;;;;;;;;;;125297:23;;;125331:12;;;:25;;125346:10;-1:-1:-1;;;;;;125331:25:0;;;;-1:-1:-1;;;;125367:44:0;-1:-1:-1;;;125367:44:0;;;;;;;125422:36;:20;;;125445:13;;125422:36;:::i;:::-;;125471:6;;;;;;;;;-1:-1:-1;;;;;125471:6:0;-1:-1:-1;;;;;125471:22:0;;125494:11;125507:22;125531:6;125471:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;125471:67:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;125471:67:0;;;;27121:1;;;;;;;;122708:2838;;;;;:::o;27656:73::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27707:14;:12;:14::i;:::-;27656:73::o;120725:99::-;120800:16;;120725:99;:::o;136096:180::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136201:10;:24;;;;136236:14;:32;136096:180::o;128572:411::-;128703:4;128742:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;128742:39:0;128785:10;128742:53;;:130;;-1:-1:-1;128821:8:0;;;128812:46;;;-1:-1:-1;;;128812:46:0;;;;128862:10;;-1:-1:-1;;;;;128821:8:0;;;;128812:44;;:46;;;;;;;;;;;;;128821:8;128812:46;;;5:2:-1;;;;30:1;27;20:12;5:2;128812:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;128812:46:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;128812:46:0;-1:-1:-1;;;;;128812:60:0;;128742:130;128720:204;;;;;-1:-1:-1;;;128720:204:0;;;;;;;;;;;;-1:-1:-1;;;128720:204:0;;;;;;;;;;;;;;;128942:5;;:33;;;-1:-1:-1;;;128942:33:0;;-1:-1:-1;;;;;128942:33:0;;;;;;;;;;;;;;;:5;;;;;:14;;:33;;;;;;;;;;;;;;:5;;:33;;;5:2:-1;;;;30:1;27;20:12;116016:36:0;;;-1:-1:-1;;;;;116016:36:0;;:::o;134071:217::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134175:1;134163:9;:13;134155:22;;;;;;134188:6;;134222:17;;134188:52;;;-1:-1:-1;;;134188:52:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;134188:6:0;;;;:22;;:52;;;;;:6;;:52;;;;;;;;:6;;:52;;;5:2:-1;;;;30:1;27;20:12;5:2;134188:52:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;134251:17:0;:29;;;;-1:-1:-1;134071:217:0:o;116637:37::-;;;;:::o;27027:18::-;;;;;;:::o;149334:414::-;149446:10;149406:19;149428:29;;;:17;:29;;;;;;149476:24;149428:29;149476:11;:24::i;:::-;149468:52;;;;;-1:-1:-1;;;149468:52:0;;;;;;;;;;;;-1:-1:-1;;;149468:52:0;;;;;;;;;;;;;;;149533:20;149556:23;;;:10;:23;;;;;:39;;;-1:-1:-1;;;;;149556:39:0;149614:28;149606:63;;;;;-1:-1:-1;;;149606:63:0;;;;;;;;;;;;-1:-1:-1;;;149606:63:0;;;;;;;;;;;;;;;149682:58;;;-1:-1:-1;;;149682:58:0;;;;;;;;;;;-1:-1:-1;;;;;149682:46:0;;;;;:58;;;;;-1:-1:-1;;149682:58:0;;;;;;;-1:-1:-1;149682:46:0;:58;;;5:2:-1;;;;30:1;27;20:12;5:2;149682:58:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;149682:58:0;;;;149334:414;;;:::o;118095:58::-;;;;;;;;;;;;;:::o;129822:937::-;129883:11;118706:30;118724:11;118706:17;:30::i;:::-;129907:25;129935:23;;;:10;:23;;;;;:41;;;130070:21;;;;;:97;;-1:-1:-1;130155:12:0;;130134:16;;130112:39;;:17;;:39;:21;:39;:::i;:::-;:55;;130070:97;:167;;;;-1:-1:-1;130222:15:0;130188:23;;;;:10;:23;;;;;:30;;;-1:-1:-1;;;130188:30:0;;;;:49;;;;;;;;;;130070:167;130048:200;;;;;;130261:14;130278:23;;;:10;:23;;;;;:30;130344:11;;130278:30;;130261:14;130344:23;;130278:30;130344:23;:15;:23;:::i;:::-;130378:11;:28;;;130419:11;;:29;;;-1:-1:-1;;;130419:29:0;;;;;;;;;;130319:48;;-1:-1:-1;;;;;;130419:11:0;;;;:16;;:29;;;;;:11;;:29;;;;;;;;:11;;:29;;;5:2:-1;;;;30:1;27;20:12;5:2;130419:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;130461:49:0;130479:23;;;:10;:23;;;;;;;;:30;;;;-1:-1:-1;;;;;130479:30:0;;;130461:49;;:17;:49;;;;;-1:-1:-1;;130461:74:0;;130546:23;;;;;;:30;;:48;;-1:-1:-1;;;;130546:48:0;-1:-1:-1;;;130546:48:0;;;130579:15;130613:5;:34;;-1:-1:-1;;;130613:34:0;;130628:10;130613:34;;;;;;;;;;;;:5;;;-1:-1:-1;130613:14:0;;:34;;;;;;;;;;;;;:5;:34;;;5:2:-1;;;;30:1;27;20:12;5:2;130613:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;130613:34:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;130613:34:0;130605:68;;;;;-1:-1:-1;;;130605:68:0;;;;;;;;;;;;-1:-1:-1;;;130605:68:0;;;;;;;;;;;;;;;130684:6;;:67;;;-1:-1:-1;;;130684:67:0;;130703:10;130684:67;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;130684:6:0;;;;:18;;:67;;;;;:6;;:67;;;;;;;;:6;;:67;;;5:2:-1;;;;30:1;27;20:12;117793:27:0;;;;;;:::o;135117:383::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135219:1;135206:10;:14;135198:23;;;;;;135232:6;;135273:7;;135232:49;;;-1:-1:-1;;;135232:49:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;135232:6:0;;;;:28;;:49;;;;;:6;;:49;;;;;;;;:6;;:49;;;5:2:-1;;;;30:1;27;20:12;5:2;135232:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;135292:7:0;:20;;;-1:-1:-1;135323:16:0;:29;;;135379:17;135302:10;135394:1;135379:17;:14;:17;:::i;:::-;135363:13;:33;;;135461:12;;:31;;;:16;:31;:::i;:::-;135439:19;:53;-1:-1:-1;135117:383:0:o;28374:210::-;4728:9;:7;:9::i;:::-;4720:18;;;;;;-1:-1:-1;;;;;28457:26:0;;28449:35;;;;;;28517:9;;28500:41;;-1:-1:-1;;;;;28500:41:0;;;;28517:9;;28500:41;;28517:9;;28500:41;28552:9;:24;;-1:-1:-1;;;;;;28552:24:0;-1:-1:-1;;;;;28552:24:0;;;;;;;;;;28374:210::o;120832:131::-;120898:7;120925:23;;;:10;:23;;;;;:30;;120832:131::o;115948:25::-;;;-1:-1:-1;;;;;115948:25:0;;:::o;120213:112::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;120290:17;:27;;-1:-1:-1;;120290:27:0;;;;;;;;;;120213:112::o;5623:109::-;4728:9;:7;:9::i;:::-;4720:18;;;;;;5696:28;5715:8;5696:18;:28::i;136284:930::-;136372:11;118706:30;118724:11;118706:17;:30::i;:::-;136396:14;136413:26;136426:12;136413;:26::i;:::-;136396:43;-1:-1:-1;;;;;;136458:22:0;;;;;;:56;;-1:-1:-1;;;;;;136484:25:0;;;;;;:17;:25;;;;;;:30;136458:56;136450:83;;;;;-1:-1:-1;;;136450:83:0;;;;;;;;;;;;-1:-1:-1;;;136450:83:0;;;;;;;;;;;;;;;136570:12;;136673:17;;136546:21;136632:36;;;:23;:36;;;;;;:59;;;:40;:59;:::i;:::-;136615:13;:76;;136593:152;;;;;-1:-1:-1;;;136593:152:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;136758:21;136782:23;;;:10;:23;;;;;;;;:30;;;;;136855:6;;:72;;-1:-1:-1;;;136855:72:0;;;;;;;;-1:-1:-1;;;;;136782:30:0;;;136855:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;136782:30;;136855:6;;;;;:22;;136782:23;;:30;;136855: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;136855:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;136855:72:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;;;;;;136940:32:0;;;;;;;:17;:32;;;;;;;;-1:-1:-1;;136940:57:0;;137008:25;;;;;;;;;;:39;;;137058:23;;;:10;:23;;;;;:30;;:39;;-1:-1:-1;;;;;;137058:39:0;;;;;;;-1:-1:-1;137154:23:0;:36;;;;:52;;;;-1:-1:-1;;136284:930:0:o;134423:303::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134599:4;-1:-1:-1;;;;;134544:60:0;134560:18;-1:-1:-1;;;;;134544:41:0;;:43;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;134544:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;134544:43:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;134544:43:0;-1:-1:-1;;;;;134544:60:0;;134536:111;;;;-1:-1:-1;;;134536:111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134658:23;;;;:10;:23;;;;;;:39;;:60;;-1:-1:-1;;;;;;134658:60:0;-1:-1:-1;;;;;134658:60:0;;;;;;;;;134423:303::o;135558:143::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135660:12;;:33;;135677:15;135660:33;:16;:33;:::i;27579:69::-;26823:10;;;;;-1:-1:-1;;;;;26823:10:0;26801;:33;26779:121;;;;-1:-1:-1;;;26779:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27628:12;:10;:12::i;132790:388::-;132925:1;132907:15;:19;:40;;;;;132946:1;132930:13;:17;132907:40;132899:70;;;;;-1:-1:-1;;;132899:70:0;;;;;;;;;;;;-1:-1:-1;;;132899:70:0;;;;;;;;;;;;;;;132996:27;;;;:10;:27;;;;;;:43;;;132980:91;;-1:-1:-1;;;132980:91:0;;133052:10;132980:91;;;;;;;;;;;;-1:-1:-1;;;;;132996:43:0;;;;132980:71;;:91;;;;;;;;;;;132996:27;:43;132980:91;;;5:2:-1;;;;30:1;27;20:12;5:2;132980:91:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;133098:25:0;;;;:10;:25;;;;;;:41;;;133082:88;;-1:-1:-1;;;133082:88:0;;133151:10;133082:88;;;;;;;;;;;;-1:-1:-1;;;;;133098:41:0;;;;-1:-1:-1;133082:68:0;;:88;;;;;133098:25;;133082:88;;;;;;133098:25;:41;133082:88;;;5:2:-1;;;;30:1;27;20:12;116352:29:0;;;;:::o;115892:19::-;;;-1:-1:-1;;;;;115892:19:0;;:::o;2078:433::-;2136:7;2380:6;2376:47;;-1:-1:-1;2410:1:0;2403:8;;2376:47;2447:5;;;2451:1;2447;:5;:1;2471:5;;;;;:10;2463:19;;;;;;2502:1;-1:-1:-1;2078:433:0;;;;;:::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;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;3325:150::-;3383:7;3415:5;;;3439:6;;;;3431:15;;;;;3087:150;3145:7;3178:1;3173;:6;;3165:15;;;;;;-1:-1:-1;3203:5:0;;;3087:150::o;147460:374::-;147531:12;;147507:21;147574:20;147531:12;147592:1;147574:20;:17;:20;:::i;:::-;147554:40;;147607:26;;:::i;:::-;-1:-1:-1;147636:32:0;;;;:21;:32;;;;;;;;147607:61;;;;;;;;;;;;;;;;;;;;;;;;;;147679:54;;147607:61;147679:14;:54::i;:::-;-1:-1:-1;147753:36:0;;;;:21;:36;;;;;147746:43;;;;;;;;;147802:12;:24;147460:374::o;139746:1820::-;139914:7;;;;140065:1207;140088:4;:11;140084:1;:15;;;140065:1207;;;140125:14;140142:19;;:8;140162:27;140177:4;140162:27;;;140186:2;140162:14;:27::i;:::-;140142:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;140142:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;140142:48:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;140142:48:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140142:48:0;-1:-1:-1;;;;;140227:25:0;;;140205:19;140227:25;;;:17;140142:48;140227:25;;;;;140142:48;;-1:-1:-1;140330:17:0;;;;140326:935;;;140368:5;;;;140326:935;140399:24;140411:11;140399;:24::i;:::-;:44;;;;;140436:7;-1:-1:-1;;;;;140427:16:0;:6;-1:-1:-1;;;;;140427:16:0;;140399:44;140395:866;;;140501:27;140531:23;;;:10;:23;;;;;140670:25;;;;140474:6;;-1:-1:-1;140474:6:0;;140531:23;;140501:27;-1:-1:-1;;;;;140670:25:0;140718:28;;140714:468;;140796:12;-1:-1:-1;;;;;140780:43:0;;140850:6;140883:20;140930:27;140945:11;140930:14;:27::i;:::-;140780:200;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;140780:200:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;140780:200:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140780:200:0;;-1:-1:-1;140714:468:0;;;141038:9;:16;;;141029:25;;141096:66;141117:44;141140:20;141117:18;141128:6;141117;:10;;:18;;;;:::i;:44::-;141096:16;;;;;:66;:20;:66;:::i;:::-;141077:16;;;:85;140714:468;141218:27;:15;141238:6;141218:27;:19;:27;:::i;:::-;141200:45;;140395:866;;;;-1:-1:-1;;140106:2:0;140101:7;140065:1207;;;;141293:75;141336:31;:29;:31::i;:::-;141293:17;;:38;;141315:15;141293:38;:21;:38;:::i;:75::-;141394:12;;141284:84;;-1:-1:-1;141394:24:0;;141284:84;141394:24;:16;:24;:::i;:::-;141379:12;:39;141456:52;141506:1;141456:45;141499:1;141456:38;141492:1;141456:31;:29;:31::i;:::-;:35;:38;:35;:38;:::i;:45::-;:49;:52;:49;:52;:::i;:::-;141437:15;:71;;141429:103;;;;;-1:-1:-1;;;141429:103:0;;;;;;;;;;;;-1:-1:-1;;;141429:103:0;;;;;;;;;;;;;;;-1:-1:-1;141552:6:0;;139746:1820;-1:-1:-1;;;;;139746:1820:0:o;118764:135::-;118844:11;;:32;;;-1:-1:-1;;;118844:32:0;;;;;;;;;;118880:10;;-1:-1:-1;;;;;118844:11:0;;:19;;:32;;;;;;;;;;;;;;:11;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;118844:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;118844:32:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;118844:32:0;-1:-1:-1;;;;;118844:46:0;;118836:55;;;;;147842:948;147979:16;147975:808;;148079:1;148070:6;:10;148066:245;;;148125:14;:21;:42;;148159:6;148125:42;:25;:42;:::i;:::-;148101:14;:66;148066:245;;;148202:1;148193:6;:10;148189:122;;;148248:14;:21;:47;;148282:11;;;;148248:47;:25;:47;:::i;:::-;148224:14;:71;148189:122;148345:1;148331:11;:15;148327:285;;;148396:26;;:52;;148435:11;148396:52;:30;:52;:::i;:::-;148367:26;:81;148327:285;;;148488:1;148474:11;:15;148470:142;;;148539:26;;:57;;148578:16;;;;148539:57;:30;:57;:::i;:::-;148510:26;:86;148470:142;147975:808;;;148644:34;;;;:21;:34;;;;;:51;;;;;;-1:-1:-1;148710:46:0;:61;;;;;;147842:948;;;:::o;27138:85::-;27198:6;;;;27197:7;27189:26;;;;;-1:-1:-1;;;27189:26:0;;;;;;;;;;;;-1:-1:-1;;;27189:26:0;;;;;;;;;;;;;;146380:1072;146458:14;146475:23;;;:10;:23;;;;;:30;;146536:20;146486:11;146536:7;:20::i;:::-;146569:23;;;;:10;:23;;;;;:41;;;:53;;;146735:30;;;;146799:39;;;;;146516:40;;-1:-1:-1;146569:23:0;;-1:-1:-1;;;;;146799:39:0;146853:28;;146849:273;;146898:30;146947:12;146898:62;;146985:54;146997:14;-1:-1:-1;;;;;146997:39:0;;:41;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;146997:41:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;146985:54:0;146975:64;;147080:14;-1:-1:-1;;;;;147080:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;147080:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;147080:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;147080:29:0;;-1:-1:-1;;146849:273:0;147134:50;147152:11;147165:9;147176:7;147134:17;:50::i;:::-;147224:19;147259:12;;147246:9;:25;;:41;;147278:9;147246:41;;;147274:1;147246:41;147224:63;;147298:69;147332:16;147322:6;147315:33;147313:36;;-1:-1:-1;;147355:11:0;147298:14;:69::i;:::-;147380:6;;:64;;;-1:-1:-1;;;147380:64:0;;-1:-1:-1;;;;;147380:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:6;;;;;:21;;:64;;;;;:6;;:64;;;;;;;:6;;:64;;;5:2:-1;;;;30:1;27;20:12;5:2;147380:64:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;147380:64:0;;;;146380:1072;;;;;;;;:::o;120971:408::-;121119:14;;121112:3;:21;;121104:57;;;;;-1:-1:-1;;;121104:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;121180:5;;-1:-1:-1;;;;;121180:5:0;:18;121199:10;121219:4;121226:25;:3;121234:16;121226:25;:7;:25;:::i;:::-;121180:72;;;;;;;;;;;;;-1:-1:-1;;;;;121180:72:0;-1:-1:-1;;;;;121180:72:0;;;;;;-1:-1:-1;;;;;121180:72:0;-1:-1:-1;;;;;121180:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;121180:72:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;121180:72:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;121180:72:0;121172:104;;;;;-1:-1:-1;;;121172:104:0;;;;;;;;;;;;-1:-1:-1;;;121172:104:0;;;;;;;;;;;;;;;121306:16;;:25;;121327:3;121306:25;:20;:25;:::i;:::-;121287:16;:44;121342:6;;:29;;;-1:-1:-1;;;121342:29:0;;-1:-1:-1;;;;;121342:29:0;;;;;;;;;;;;;;;:6;;;;;:18;;:29;;;;;:6;;:29;;;;;;;:6;;:29;;;5:2:-1;;;;30:1;27;20:12;144922:1450:0;145082:7;145102:14;145119:26;145132:12;145119;:26::i;:::-;145102:43;-1:-1:-1;;;;;;145164:22:0;;;;;;:56;;-1:-1:-1;;;;;;145190:25:0;;;;;;:17;:25;;;;;;:30;145164:56;145156:83;;;;;-1:-1:-1;;;145156:83:0;;;;;;;;;;;;-1:-1:-1;;;145156:83:0;;;;;;;;;;;;;;;145276:12;;145321:10;;145364:6;;145406:11;;-1:-1:-1;;;;;145364:6:0;;;;145252:21;;145406:23;;145422:6;145406:23;:15;:23;:::i;:::-;145381:48;;145454:14;145440:11;:28;;;;145507:367;;;;;;;;145564:6;145507:367;;;;145540:1;145507:367;;;;145602:13;145507:367;;;;145649:1;145507:367;;;;145675:1;145507:367;;;;145699:6;-1:-1:-1;;;;;145507:367:0;;;;;145737:16;:89;;145822:3;145737:89;;;145756:7;;145802:8;;;145756:55;;;-1:-1:-1;;;145756:55:0;;;;;;;;-1:-1:-1;;;;;145756:55:0;;;;;;;145802:8;;;145756:55;;;;;:7;;;:14;;:55;;;;;;;;;;;;;;;:7;;:55;;;5:2:-1;;;;30:1;27;20:12;5:2;145756:55:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;145756:55:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;145756:55:0;145737:89;-1:-1:-1;;;;;145507:367:0;;;;;145849:13;145507:367;;145481:23;;;;:10;:23;;;;;;;;;:393;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;145481:393:0;;;-1:-1:-1;;;;;;145481:393:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;145481:393:0;;;;-1:-1:-1;;;145481:393:0;;;;;;;;;;;;;;-1:-1:-1;;;145887:36:0;;;;:23;:36;;;;;;:52;;;145950:11;;:35;;-1:-1:-1;;;145950:35:0;;-1:-1:-1;;;;;145950:35:0;;;;;;;;;;;;;;;:11;;;;;:16;;:35;;;;;;;;;;145887:36;145950:11;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;145950:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;;;;;;145998:25:0;;;;;;:17;:25;;;;;:39;;;146048:36;;-1:-1:-1;146070:6:0;;146079:1;;146048:14;:36::i;:::-;146176:13;146133:16;:29;146150:11;146133:29;;;;;;;;;;;:40;;:56;;;;146200:7;-1:-1:-1;;;;;146200:17:0;;146218:6;146226:12;146240:11;146253:13;146268:6;146276:14;146200:91;;;;;;;;;;;;;-1:-1:-1;;;;;146200:91:0;-1:-1:-1;;;;;146200: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;146200:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;146200:91:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;146200:91:0;;;;146315:18;146331:1;146315:11;:15;;:18;;;;:::i;:::-;146302:10;:31;-1:-1:-1;146353:11:0;;144922:1450;-1:-1:-1;;;;;;;;144922:1450:0:o;7622:225::-;7683:14;;:::i;:::-;-1:-1:-1;7811:28:0;;;;;;;;;7819:11;;7811:28;;7776:4;7766:15;;;7811:28;;;;7622:225;;;:::o;8657:523::-;8717:16;8754:12;8761:4;8754:6;:12::i;:::-;8746:21;;;;;;8780:10;8793:14;8802:4;8793:8;:14::i;:::-;8780:27;;8818:23;8858:5;8844:20;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;8818:46;;8877:11;8905:27;8920:4;:11;;;8905:14;:27::i;:::-;8891:11;;;;:41;;-1:-1:-1;8943:12:0;;8966:181;8987:5;8983:1;:9;8966:181;;;9024:19;9036:6;9024:11;:19::i;:::-;9014:29;;9070:24;;;;;;;;9078:7;9070:24;;;;9087:6;9070:24;;;9058:6;9065:1;9058:9;;;;;;;;;;;;;;;;;:36;9119:16;;;;8994:3;;8966:181;;;-1:-1:-1;9166:6:0;;8657:523;-1:-1:-1;;;;;8657:523:0:o;10640:549::-;10725:8;;10700:4;;10725:12;;;;:30;;-1:-1:-1;10741:8:0;;10753:2;-1:-1:-1;10741:14:0;10725:30;10717:39;;;;;;10769:11;10783:27;10798:4;:11;;;10783:14;:27::i;:::-;10832:8;;10898:11;;;;;:20;;10963:13;;10769:41;;-1:-1:-1;10832:17:0;;;;;10963:13;10898:20;11054:11;;11051:2;;;11124:3;11120:2;11116:12;11111:3;11107:22;11099:6;11095:35;11085:45;;11051:2;-1:-1:-1;11175:6:0;10640:549;-1:-1:-1;;;;10640:549:0:o;10137:291::-;10225:8;;10200:4;;10237:1;10225:13;10217:22;;;;;;10286:11;;;;10350:13;;10250:11;10342:22;;10394:11;;:26;;10416:4;10394:26;;;10408:5;10394:26;10387:33;10137:291;-1:-1:-1;;;;10137:291:0:o;144248:666::-;144327:7;144390:23;;;:10;:23;;;;;:39;;;144327:7;;-1:-1:-1;;;;;144390:39:0;:55;144386:178;;144497:23;;;;:10;:23;;;;;;;;:39;;;144481:71;;-1:-1:-1;;;144481:71:0;;;;-1:-1:-1;;;;;144497:39:0;;;;144481:69;;:71;;;;;144497:23;;144481:71;;;;;;;;;144497:39;144481:71;;;5:2:-1;;;;30:1;27;20:12;5:2;144481:71:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;144481:71:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;144481:71:0;;-1:-1:-1;144386:178:0;144600:12;;144658:34;144600:12;144676:15;144658:34;:17;:34;:::i;:::-;144623:23;;;;:10;:23;;;;;;:32;;;;:69;;;;144703:30;;;:46;;-1:-1:-1;;;;144703:46:0;-1:-1:-1;;;144703:46:0;;;144760:6;;;144805:30;;;144760:76;;-1:-1:-1;;;144760:76:0;;;;;;;;;;;;;;-1:-1:-1;;;;;144805:30:0;;;144760:76;;;;;;:6;;;:16;;:76;;;;;144623:23;;144760:76;;;;;144623:23;144760:6;:76;;;5:2:-1;;;;30:1;27;20:12;5:2;144760:76:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;144854:23:0;;;;:10;:23;;;;;:30;:52;;-1:-1:-1;144889:16:0;144854:52;:34;:52;:::i;121387:166::-;121474:16;;:28;;121495:6;121474:28;:20;:28;:::i;:::-;121455:16;:47;121513:6;;:32;;;-1:-1:-1;;;121513:32:0;;-1:-1:-1;;;;;121513:32:0;;;;;;;;;;;;;;;:6;;;;;:18;;:32;;;;;:6;;:32;;;;;;;:6;;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;121513:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5882:187:0;-1:-1:-1;;;;;5956:22:0;;5948:31;;;;;;6016:6;;5995:38;;-1:-1:-1;;;;;5995:38:0;;;;6016:6;;5995:38;;6016:6;;5995:38;6044:6;:17;;-1:-1:-1;;;;;;6044:17:0;-1:-1:-1;;;;;6044:17:0;;;;;;;;;;5882:187::o;131971:376::-;132102:22;;:34;;132129:6;132102:34;:26;:34;:::i;:::-;132077:22;:59;132180:1;132147:23;;;:10;:23;;;;;;;;:30;;:34;;;132200:5;;:37;;-1:-1:-1;;;132200:37:0;;-1:-1:-1;;;;;132200:37:0;;;;;;;;;;;;;;;:5;;;;;:14;;:37;;;;;132147:23;;132200:37;;;;;;;;;;:5;:37;;;5:2:-1;;;;30:1;27;20:12;5:2;132200:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;132200:37:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;132200:37:0;132192:69;;;;;-1:-1:-1;;;132192:69:0;;;;;;;;;;;;-1:-1:-1;;;132192:69:0;;;;;;;;;;;;;;;132272:6;;132316:22;;132272:67;;;-1:-1:-1;;;132272:67:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;132272:6:0;;;;:22;;:67;;;;;:6;;:67;;;;;;;;:6;;:67;;;5:2:-1;;;;30:1;27;20:12;1082:107:0;1140:7;1172:1;1167;:6;;:14;;1180:1;1167:14;;27294:58;27339:5;27330:14;;-1:-1:-1;;27330:14:0;;;27294:58::o;148798:192::-;148860:7;148888:3;:10;148902:2;148888:16;148880:43;;;;;-1:-1:-1;;;148880:43:0;;;;;;;;;;;;-1:-1:-1;;;148880:43:0;;;;;;;;;;;;;;;-1:-1:-1;148965:14:0;;;;;;;;148798:192::o;27231:55::-;27265:6;:13;;-1:-1:-1;;27265:13:0;27274:4;27265:13;;;27231:55::o;18562:2976::-;18681:12;18746:7;18737:6;:16;18719:6;:13;:35;;18711:44;;;;;;18766:22;18830:15;;18863:2392;;;;21411:4;21405:11;21392:24;;21466:4;21455:9;21451:20;21445:4;21438:34;18823:2668;;18863:2392;19060:4;19054:11;19041:24;;19765:2;19756:7;19752:16;20224:9;20217:17;20211:4;20207:28;20170:9;20159;20155:25;20125:133;20299:7;20295:2;20291:16;20728:6;20655:9;20648:17;20642:4;20638:28;20593:9;20585:6;20581:22;20543:154;20509:252;20331:652;20792:3;20788:2;20785:11;20331:652;;;20950:9;;20939:21;;20838:4;20830:13;;;;20875;20331:652;;;-1:-1:-1;;21007:26:0;;;21231:2;21214:11;-1:-1:-1;;21210:25:0;21204:4;21197:39;-1:-1:-1;;21521:9:0;18562:2976;-1:-1:-1;;;;18562:2976:0:o;9287:342::-;9368:8;;9347:4;;9364:31;;-1:-1:-1;9390:5:0;9383:12;;9364:31;9444:11;;;;9507:13;;9408:11;9499:22;;6413:4;9548:24;;9544:55;;;9594:5;9587:12;;;;;;9544:55;-1:-1:-1;9617:4:0;;9287:342;-1:-1:-1;;;9287:342:0:o;12095:422::-;12177:8;;12156:4;;12173:27;;-1:-1:-1;12199:1:0;12192:8;;12173:27;12213:10;12226:1;12213:14;;12238:12;12267:27;12282:4;:11;;;12267:14;:27::i;:::-;12253:11;;;;12333:8;;12253:41;;;;-1:-1:-1;12319:22:0;12352:133;12369:6;12359:7;:16;12352:133;;;12411:20;12423:7;12411:11;:20::i;:::-;12466:7;;;;;12401:30;;;;12352:133;;;-1:-1:-1;12504:5:0;;12095:422;-1:-1:-1;;;12095:422:0:o;13951:552::-;14089:13;;14010:4;;14081:22;;6319:4;14130:26;;14126:369;;;14179:1;14172:8;;;;;14126:369;6366:4;14200:25;;;:83;;-1:-1:-1;6413:4:0;14230:25;;;;;:52;;-1:-1:-1;6460:4:0;14259:23;;14230:52;14196:299;;;14305:1;14298:8;;;;;14196:299;6413:4;14326:24;;14322:173;;;-1:-1:-1;;14391:35:0;;-1:-1:-1;14384:42:0;;14322:173;-1:-1:-1;;14462:33:0;;-1:-1:-1;14455:40:0;;12569:1327;12727:13;;12625:4;;;;12719:22;;6319:4;12768:26;;12764:1098;;;12819:1;12809:11;;12764:1098;;;6366:4;12850:25;;12846:1016;;;-1:-1:-1;;12900:30:0;;;-1:-1:-1;12846:1016:0;;;6413:4;12952:24;;12948:914;;;13047:4;13040:5;13036:16;13127:1;13119:6;13115:14;13105:24;;13285:7;13281:2;13277:16;13272:3;13268:26;13259:6;13253:13;13249:46;13383:1;13374:7;13370:15;13361:7;13357:29;13346:40;;13002:399;;;;;6460:4;13433:23;;13429:433;;;-1:-1:-1;;13483:28:0;;;-1:-1:-1;13429:433:0;;;13610:4;13603:5;13599:16;13655:1;13647:6;13643:14;13633:24;;13728:7;13724:2;13720:16;13715:3;13711:26;13702:6;13696:13;13692:46;13833:1;13824:7;13820:15;13811:7;13807:29;13796:40;;13565:286;;;-1:-1:-1;13881:7:0;12569:1327;-1:-1:-1;;12569:1327:0:o;118328:31423::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;118328:31423:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;118328:31423:0;;;-1:-1:-1;118328:31423:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;
Swarm Source
bzzr://5303fd765be1bd98f895304344671726e733bd897ca8b4c4e93a97b01f9a2488
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.