Transactions
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Read Proxy
Write Contract
Write Proxy
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- EtnyStakingImplementation
- Optimization enabled
- true
- Compiler version
- v0.8.26+commit.8a97fa7a
- Optimization runs
- 200
- EVM Version
- istanbul
- Verified at
- 2024-08-25T12:12:11.633011Z
Contract source code
// File: contracts/Enums.sol
pragma solidity ^0.8.0;
library Enums {
enum BaseStakeStatus {
PENDING,
APPROVED,
DECLINED,
CANCELED,
TERMINATED
}
enum ExtendedStakeStatus {
PENDING,
APPROVED,
DECLINED,
CANCELED,
TERMINATED
}
enum StakeContractStatus {
PENDING,
APPROVED,
DECLINED,
CANCELED,
TERMINATED
}
enum EntityType{
STAKER,
NODE_OPERATOR
}
enum StakeType{
BASE_STAKE,
EXTENDED_STAKE
}
}
// File: contracts/Models.sol
pragma solidity ^0.8.0;
library Models {
struct BaseStake {
address stakeHolderAddress;
address rewardAddress;
address nodeAddress;
uint256 timestamp;
uint64 amount;
uint16 period;
Enums.BaseStakeStatus status;
uint256 stakeContractId;
}
struct ExtendedStake {
address stakeHolderAddress;
address rewardAddress;
address nodeAddress;
uint256 timestamp;
uint64 amount;
uint64 amountBooked;
uint64 stakingContracts;
uint16 period; // in months
uint8 operatorRewardPercentage;
bool allowMultipleOp;
bool autoConfirm;
Enums.ExtendedStakeStatus status;
mapping(uint64 => uint256) stakingContractsMapping;
mapping(Enums.StakeContractStatus => uint64) stakingContractsStatuses;
}
struct StakeContract {
address stakeHolder;
address stakeRewardAddress;
address nodeAddress;
address nodeRewardAddress;
uint256 timestamp;
uint64 amount;
uint64 operatorRewardPercentage;
uint16 period; //in months
uint256 canceledOn;
uint256 approvedOn;
uint256 expiresOn;
Enums.StakeContractStatus status;
uint256 stakeId;
Enums.StakeType stakeType;
bool isOperatorPerformingBad;
}
}
// File: contracts/interfaces/IEtnyStaking.sol
pragma solidity ^0.8.0;
interface IEtnyStaking {
function addBaseStakeRequest(
address nodeAddress,
uint64 amount,
uint16 period
) external returns (uint256);
function addExtendedStakeRequest(
address nodeAddress,
uint64 amount,
address rewardAddress,
uint16 period,
uint8 opReward,
bool allowMultipleOp,
bool autoConfirm
) external returns (uint256);
function approveBaseStakeRequest(
uint256 baseStakeId,
address rewardAddress
) external returns (bool);
function cancelBaseStakeRequest(
uint256 baseStakeId
) external returns (bool);
function lockBaseStakeRequest(
uint256 baseStakeId
) external returns (bool);
function declineBaseStakeRequest(
uint256 baseStakeId
) external returns (bool);
// extended stake
function cancelExtendedStakeRequest(
uint256 extendedStakeId
) external returns (bool);
function applyExtendedStakeRequest(
uint256 extendedStakeID,
uint64 amount,
address rewardAddress
) external returns (bool);
function freeExtendedStakeRequest(
uint256 extendedStakeId
) external returns (bool);
function getLockedBalanceAtStakeInWei(
address wallet
) external returns (uint256);
}
// File: contracts/interfaces/IOwnable.sol
pragma solidity ^0.8.0;
interface IOwnable {
function owner() external view returns (address);
}
// File: contracts/Initializable.sol
pragma solidity ^0.8.0;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
/// @dev Returns true if and only if the function is running in the constructor
function _isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
address self = address(this);
uint256 cs;
// solhint-disable-next-line no-inline-assembly
assembly {cs := extcodesize(self)}
return cs == 0;
}
}
// File: contracts/Ownable.sol
pragma solidity ^0.8.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
* @author crypto-pumpkin
*
* By initialization, the owner account will be the one that called initializeOwner. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract Ownable is Initializable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(){
initializeOwner();
}
/**
* @dev COVER : Initializes the contract setting the deployer as the initial owner.
*/
function initializeOwner() internal initializer {
_owner = msg.sender;
emit OwnershipTransferred(address(0), _owner);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(_owner == msg.sender, "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
// File: contracts/interfaces/ERC20Interface.sol
pragma solidity ^0.8.0;
interface ERC20Interface {
function totalSupply() external view returns (uint);
function balanceOf(address tokenOwner) external view returns (uint balance);
function allowance(address tokenOwner, address spender) external view returns (uint remaining);
function transfer(address to, uint tokens) external returns (bool success);
function approve(address spender, uint tokens) external returns (bool success);
function transferFrom(address from, address to, uint tokens) external returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
// File: contracts/CompanyWallet.sol
pragma solidity ^0.8.0;
contract CompanyWallet is Ownable {
mapping(address => bool) companyAddresses;
constructor(){
companyAddresses[msg.sender] = true;
}
function addCompanyWallet(address companyAddress) public onlyOwner {
companyAddresses[companyAddress] = true;
}
function removeCompanyWallet(address oldCompanyAddress) public onlyOwner {
companyAddresses[oldCompanyAddress] = false;
}
/**
* @dev Throws if called by any account other than other of company wallets.
*/
modifier onlyCompanyWallet() {
require(
companyAddresses[msg.sender],
"CompanyWallet: caller is not a wallet from company"
);
_;
}
}
// File: contracts/Delegated.sol
pragma solidity ^0.8.0;
/**
* Copyright (C) 2018, 2019, 2020 Ethernity HODL UG
*
* This file is part of ETHERNITY PoX SC.
*
* ETHERNITY PoE SC is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
contract Delegated is Ownable {
address public callerAddress;
event ProxyTransferred(address indexed _from, address indexed _to);
/*constructor() {
callerAddress = msg.sender;
}*/
modifier onlyDelegate {
require(msg.sender == callerAddress);
_;
}
function transferProxy(address _newProxy) public onlyOwner {
callerAddress = _newProxy;
}
}
// File: contracts/EtnyStakingStorage.sol
pragma solidity ^0.8.0;
/**
* Copyright (C) 2018, 2019, 2020 Ethernity HODL UG
*
* This file is part of ETHERNITY PoX SC.
*
* ETHERNITY PoE SC is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
contract EtnyStakingStorage is Delegated, CompanyWallet {
constructor() {
_owner = msg.sender;
companyAddresses[msg.sender] = true;
}
address public implementation;
address[] internal versions;
address public _owner;
address internal _etnyPartnershipProgramSmartContractAddress;
address internal _etnyTokenSmartContractAddress;
address internal _etnyNFTIntegrationContractAddress;
// contracts and requests lists
Models.BaseStake[] internal _baseStakesList;
Models.ExtendedStake[] internal _extendedStakeList;
Models.StakeContract[] internal _stakingContractsList;
mapping(address => uint256[]) internal _stakerBaseStakeRequests;
mapping(address => uint256[]) internal _stakerExtendedStakeRequests;
mapping(address => uint256[]) internal _nodeBaseStakeRequests;
mapping(address => bool) internal _nodeActiveBaseStake;
mapping(address => uint256[]) internal _nodeExtendedStakeRequests;
mapping(address => uint256[]) internal _nodeExtendedContracts;
mapping(address => uint256) internal _nodeStakingTotal;
mapping(uint256 => uint256) internal _baseStakePenalty;
mapping(address => uint256) internal _tokensLockedInStaking;
mapping(address => bool) internal _canceledBaseStakeNodes;
//technical properties
uint256 maxTokens = 75000;
uint256 maxNFTTokens = 225000;
uint8 apyPercentage = 10;
uint8 minPeriodStakeContractInMonths = 6;
uint64 totalSupply = 15000000;
uint64 minBaseStakeAmount = 1976;
uint64 minBaseStakeNFTAmount = 700;
uint64 minExtendedStakeAmount = 3024;
uint64 maxBaseStakeAmount = 75000;
uint64 nodesStakeMinAmount = 5000;
}
// File: contracts/utils.sol
pragma solidity ^0.8.0;
library Utils {
function computeExpirationDate(uint16 period, uint256 approvedOn) public view returns (uint256){
uint256 diff = 1;
if (block.timestamp - approvedOn >= 1 days)
diff = (block.timestamp - approvedOn) / 1 days;
uint256 duration = period * 30;
uint256 quotient = diff / duration;
uint256 remainder = diff % duration;
uint256 computedExpectedExpiration = 0;
if (remainder <= (duration - 30))
computedExpectedExpiration = approvedOn + (duration * (quotient + 1)) * 1 days;
else
computedExpectedExpiration = approvedOn + (duration * (quotient + 2)) * 1 days;
return computedExpectedExpiration;
}
}
// File: contracts/EtnyStakingImplementation.sol
pragma solidity ^0.8.0;
//must exists a base stake when applying or creating extended stake
contract EtnyStakingImplementation is IEtnyStaking, EtnyStakingStorage {
uint256 private constant ONEHUNDREDYEARS = 4850176343;
/// Base Stake events
event NewBaseStake(address indexed staker, uint256 baseStakeId);
event BaseStakeApproved(uint256 baseStakeId, uint256 nodeStakingTotal);
event ApplyPenaltiesToBaseStakeByCompany(uint256 nodeStakingTotal);
/// Base Stake Contract events
event NewStakeContract(address indexed staker, address indexed node, uint256 contractId);
event BaseStakeContractTerminated(uint256 stakeContractId);
event BaseStakeContractCanceled(uint256 stakeContractId);
event BaseStakeContractExtendedForPenalties(uint256 contractId);
/// Extended Stake events
event NewExtendedStake(address indexed staker, uint256 baseStakeId);
event ExtendedStakeTerminated(uint256 extendedStakeId);
event ExtendedStakeCanceled(uint256 extendedStakeId);
event ExtendedStakeFreed(uint256 extendedStakeId, uint256 tokensLockedInStaking);
event NodeAppliedToExtendedStake(address indexed node, uint256 extendedStakeId, uint256 nodeStakingTotal);
/// Extended Stake Contract events
event ExtendedStakeContractTerminated(uint256 contractId, uint256 extendedContractStakeId);
event ExtendedStakeContractCanceled(uint256 contractId, uint256 extendedContractStakeId);
event ExtendedStakeContractApproved(uint256 contractId, uint256 extendedContractStakeId);
event ExtendedStakeContractDeclined(uint256 contractId, uint256 extendedContractStakeId);
constructor() {
_owner = msg.sender;
}
/// @notice Add new Base Stake Request
function addBaseStakeRequest(
address nodeAddress,
uint64 amount,
uint16 period
) public onlyDelegate override returns (uint256 _rowNumber) {
require(
_etnyTokenSmartContractAddress != address(0),
"EtnyStaking: Something went wrong. The Ethernity Cloud SmartContract address is not correctly setup!"
);
require(
nodeAddress != address(0),
"EtnyStaking: node address is the zero address"
);
require(
msg.sender != nodeAddress,
"EtnyStaking: The node address must be different than current one!"
);
require(
period >= minPeriodStakeContractInMonths,
"EtnyStaking: The staking period is to low!"
);
require(
amount >= minBaseStakeAmount && amount <= maxBaseStakeAmount,
"EtnyStaking: amount must be between minimum and maximum values!");
require(
_nodeStakingTotal[nodeAddress] == 0,
"EtnyStaking: Node already has an existing base stake!"
);
require(
_nodeActiveBaseStake[nodeAddress] == false,
"EtnyStaking: Node already has an existing base stake!"
);
uint nodeBalance = getEtnyTokens(nodeAddress);
require(
nodeBalance == 0,
"EtnyStaking: Node has ETNY tokens!"
);
uint etnyBalance = getEtnyTokens(msg.sender);
require(
etnyBalance - _tokensLockedInStaking[msg.sender] >= amount,
"EtnyStaking: The amount exceeds balance available for staking!"
);
/*bool hasACanceledContractUnterminated = false;
for(uint256 i =0; i< _nodeBaseStakeRequests[nodeAddress].length; i++){
uint256 _contractIndex = _nodeBaseStakeRequests[nodeAddress][i];
Models.StakeContract storage _stakeContract = _stakingContractsList[_contractIndex];
if(_stakeContract.status == Enums.StakeContractStatus.CANCELED
&& _stakeContract.expiresOn < block.timestamp)
hasACanceledContractUnterminated = true;
}
require(
hasACanceledContractUnterminated == false,
"EtnyStaking: The node has an active base stake!"
);
*/
_stakerBaseStakeRequests[payable(msg.sender)].push(_baseStakesList.length);
_rowNumber = _baseStakesList.length;
_nodeBaseStakeRequests[nodeAddress].push(_rowNumber);
emit NewBaseStake(msg.sender, _rowNumber);
(Models.StakeContract storage stakeContract, uint256 stakeContractID) = addStakeContract(msg.sender, nodeAddress, address(0), period, amount, _rowNumber, 100);
stakeContract.stakeType = Enums.StakeType.BASE_STAKE;
_baseStakesList.push(
Models.BaseStake({
stakeHolderAddress: msg.sender,
rewardAddress: address(0),
nodeAddress: nodeAddress,
timestamp: block.timestamp,
amount: amount,
period: period,
status: Enums.BaseStakeStatus.PENDING,
stakeContractId: stakeContractID
})
);
_tokensLockedInStaking[msg.sender] += amount;
_nodeActiveBaseStake[nodeAddress] = true;
/*uint value = 10 ** uint(18);
ERC20Interface(_etnyTokenSmartContractAddress).transferFrom(msg.sender, address(this), amount * value);
*/
return _rowNumber;
}
function getBaseStakeRequestTotal() public onlyDelegate view returns (uint256 count){
return _baseStakesList.length;
}
function getBaseStake(uint256 baseStakeId)
external onlyDelegate
view
returns (
uint256 _baseStakeId,
address stakeHolderAddress,
address rewardAddress,
address nodeAddress,
uint256 timestamp,
uint64 amount,
uint64 period,
Enums.BaseStakeStatus status,
Enums.StakeType stakeType
)
{
require(
baseStakeId < _baseStakesList.length,
"EtnyStaking: Invalid Base Stake ID provided!"
);
Models.BaseStake memory _stake = _baseStakesList[baseStakeId];
return (
baseStakeId,
_stake.stakeHolderAddress,
_stake.rewardAddress,
_stake.nodeAddress,
_stake.timestamp,
_stake.amount,
_stake.period,
_stake.status,
Enums.StakeType.BASE_STAKE
);
}
function approveBaseStakeRequest(uint256 baseStakeId, address rewardAddress) public onlyDelegate override returns (bool){
require(
baseStakeId < _baseStakesList.length,
"EtnyStaking: Invalid Base Stake ID provided!"
);
require(
rewardAddress != address(0),
"EtnyStaking: Reward address is the zero address!"
);
require(
rewardAddress != msg.sender,
"EtnyStaking: The node address should be different than reward address!"
);
Models.BaseStake storage _stake = _baseStakesList[baseStakeId];
require(
msg.sender == _stake.nodeAddress,
"EtnyStaking: only node operator can approve base stake!"
);
require(
_stake.status == Enums.BaseStakeStatus.PENDING,
"EtnyStaking: stake must be new to be approved!"
);
_stake.status = Enums.BaseStakeStatus.APPROVED;
_stake.rewardAddress = rewardAddress;
Models.StakeContract storage _contract = _stakingContractsList[_stake.stakeContractId];
_contract.status = Enums.StakeContractStatus.APPROVED;
_contract.approvedOn = block.timestamp;
_contract.nodeRewardAddress = rewardAddress;
_nodeStakingTotal[msg.sender] += _contract.amount;
emit BaseStakeApproved(baseStakeId, _nodeStakingTotal[msg.sender]);
return true;
}
function cancelBaseStakeRequest(uint256 baseStakeId) public onlyDelegate override returns (bool){
require(
baseStakeId < _baseStakesList.length,
"EtnyStaking: Invalid Base Stake ID provided!"
);
Models.BaseStake storage _stake = _baseStakesList[baseStakeId];
require(
msg.sender == _stake.stakeHolderAddress,
"EtnyStaking: Only staker can cancel this request!"
);
require(
_stake.status == Enums.BaseStakeStatus.PENDING || _stake.status == Enums.BaseStakeStatus.APPROVED,
"EtnyStaking: Stake is having different status!"
);
_stake.status = Enums.BaseStakeStatus.CANCELED;
Models.StakeContract storage _contract = _stakingContractsList[_stake.stakeContractId];
if (_contract.status == Enums.StakeContractStatus.PENDING)
{
//terminateBaseStakeContract(_contract);
_contract.status = Enums.StakeContractStatus.TERMINATED;
_contract.canceledOn = block.timestamp;
_contract.expiresOn = block.timestamp;
_tokensLockedInStaking[_contract.stakeHolder] -= _contract.amount;
_nodeActiveBaseStake[_contract.nodeAddress] = false;
// when in pending node has no tokens on staking
//_nodeStakingTotal[msg.sender] -= _contract.amount;
emit BaseStakeContractTerminated(_stake.stakeContractId);
}
else
{
_contract.status = Enums.StakeContractStatus.CANCELED;
_contract.canceledOn = block.timestamp;
_canceledBaseStakeNodes[_contract.nodeAddress] = true;
emit BaseStakeContractCanceled(_stake.stakeContractId);
for (uint256 i = 0; i < _nodeExtendedContracts[_contract.nodeAddress].length; i++) {
uint256 _contractId = _nodeExtendedContracts[_contract.nodeAddress][i];
Models.StakeContract storage _extendedContract = _stakingContractsList[_contractId];
Models.ExtendedStake storage _extentedStake = _extendedStakeList[_extendedContract.stakeId];
if (_extendedContract.status == Enums.StakeContractStatus.PENDING
|| _extendedContract.status == Enums.StakeContractStatus.APPROVED)
_extentedStake.stakingContractsStatuses[_extendedContract.status] -= 1;
if (_extendedContract.status == Enums.StakeContractStatus.PENDING)
{
_extendedContract.status = Enums.StakeContractStatus.TERMINATED;
_extendedContract.canceledOn = block.timestamp;
_extendedContract.expiresOn = block.timestamp;
emit ExtendedStakeContractTerminated(_contractId, _extendedContract.stakeId);
// always unlock onlk stake.amount, never contract.amount
// _tokensLockedInStaking[_extendedContract.stakeHolder] -= _extendedContract.amount;
_nodeStakingTotal[_extendedContract.nodeAddress] -= _extendedContract.amount;
_extentedStake.amountBooked -= _extendedContract.amount;
_extentedStake.stakingContractsStatuses[_extendedContract.status] += 1;
}
else if (_extendedContract.status == Enums.StakeContractStatus.APPROVED)
{
_extendedContract.status = Enums.StakeContractStatus.CANCELED;
_extendedContract.canceledOn = block.timestamp;
_extendedContract.expiresOn = Utils.computeExpirationDate(_extendedContract.period, _extendedContract.approvedOn);
_extentedStake.stakingContractsStatuses[_extendedContract.status] += 1;
emit ExtendedStakeContractCanceled(_contractId, _extendedContract.stakeId);
}
if (_contract.expiresOn < _extendedContract.expiresOn)
_contract.expiresOn = _extendedContract.expiresOn;
if (_extentedStake.status == Enums.ExtendedStakeStatus.APPROVED
&& _extentedStake.stakingContractsStatuses[Enums.StakeContractStatus.APPROVED] == 0)
_extentedStake.status = Enums.ExtendedStakeStatus.CANCELED;
}
//no extended stake where made on the node
if (_contract.expiresOn == 0) {
if (_contract.amount < nodesStakeMinAmount)
{
//_contract.expiresOn = block.timestamp;
//_contract.status = Enums.StakeContractStatus.TERMINATED;
//_canceledBaseStakeNodes[_contract.nodeAddress] = false;
//terminateBaseStakeContract(_contract);
_contract.status = Enums.StakeContractStatus.TERMINATED;
_contract.canceledOn = block.timestamp;
_contract.expiresOn = block.timestamp;
_tokensLockedInStaking[_contract.stakeHolder] -= _contract.amount;
_nodeActiveBaseStake[_contract.nodeAddress] = false;
_canceledBaseStakeNodes[_contract.nodeAddress] = false;
_nodeStakingTotal[_contract.nodeAddress] -= _contract.amount;
emit BaseStakeContractTerminated(_stake.stakeContractId);
} else
_contract.expiresOn = Utils.computeExpirationDate(_contract.period, _contract.approvedOn);
}
}
return true;
}
function lockBaseStakeRequest(uint256 baseStakeId) public onlyCompanyWallet override returns (bool){
require(
baseStakeId < _baseStakesList.length,
"EtnyStaking: Invalid Base Stake ID provided!"
);
Models.BaseStake storage _stake = _baseStakesList[baseStakeId];
require(
_stake.status == Enums.BaseStakeStatus.APPROVED,
"EtnyStaking: Stake is having different status!"
);
_stake.status = Enums.BaseStakeStatus.CANCELED;
Models.StakeContract storage _contract = _stakingContractsList[_stake.stakeContractId];
_contract.status = Enums.StakeContractStatus.CANCELED;
_contract.canceledOn = block.timestamp;
_contract.expiresOn = 4850176343; // 12.09.2123
return true;
}
function terminateBaseStakeContract(Models.StakeContract storage _contract) internal returns (bool){
if (_contract.status != Enums.StakeContractStatus.PENDING) {
_nodeStakingTotal[msg.sender] -= _contract.amount;
}
_contract.status = Enums.StakeContractStatus.TERMINATED;
_contract.canceledOn = block.timestamp;
_contract.expiresOn = block.timestamp;
_tokensLockedInStaking[_contract.stakeHolder] -= _contract.amount;
_nodeActiveBaseStake[_contract.nodeAddress] = false;
_canceledBaseStakeNodes[_contract.nodeAddress] = false;
return true;
}
function declineBaseStakeRequest(uint256 baseStakeId) public onlyDelegate override returns (bool){
require(
baseStakeId < _baseStakesList.length,
"EtnyStaking: Invalid Base Stake ID provided!"
);
Models.BaseStake storage _stakePot = _baseStakesList[baseStakeId];
require(
msg.sender == _stakePot.nodeAddress,
"EtnyStaking: Only node operator can decline this request!"
);
require(
_stakePot.status == Enums.BaseStakeStatus.PENDING,
"EtnyStaking: Stake is having different status!"
);
_stakePot.status = Enums.BaseStakeStatus.DECLINED;
Models.StakeContract storage _contract = _stakingContractsList[_stakePot.stakeContractId];
_contract.status = Enums.StakeContractStatus.DECLINED;
_tokensLockedInStaking[_contract.stakeHolder] -= _contract.amount;
_nodeStakingTotal[msg.sender] = 0;
_nodeActiveBaseStake[msg.sender] = false;
return true;
}
/// @notice Add new Extended Stake Request
/// returns extended stake id
function addExtendedStakeRequest(
address nodeAddress,
uint64 amount,
address rewardAddress,
uint16 period,
uint8 opReward,
bool allowMultipleOp,
bool autoConfirm
) public onlyDelegate override returns (uint256 _extendedStakeId) {
require(
_etnyTokenSmartContractAddress != address(0),
"EtnyStaking: Something went wrong. The Ethernity Cloud SmartContract address is not correctly setup!"
);
if (opReward != 100)
require(
rewardAddress != address(0),
"EtnyStaking: reward address is the zero address"
);
require(
amount >= minExtendedStakeAmount,
"EtnyStaking: The amount is to0 low!"
);
require(
period >= minPeriodStakeContractInMonths,
"EtnyStaking: The period is to low!"
);
require(
opReward < 101,
"EtnyStaking: The operator reward percentage is too high!"
);
require(
opReward >= 0,
"EtnyStaking: The operator reward percentage is too low!"
);
require(
rewardAddress != msg.sender,
"EtnyStaking: The current address should be different than reward address!"
);
if (nodeAddress != address(0)) {
require(
!_canceledBaseStakeNodes[nodeAddress],
"EtnyStaking: The base stake contract on the node was canceled!"
);
require(
_nodeStakingTotal[nodeAddress] > 0,
"EtnyStaking: The node doesn't have any base stake setup!"
);
require(
msg.sender != nodeAddress,
"EtnyStaking: The node address must be different!"
);
require(
rewardAddress != nodeAddress,
"EtnyStaking: The node address should be different than reward address!"
);
require(
_nodeStakingTotal[nodeAddress] + amount <= maxTokens,
"EtnyStaking: The amount exceeds the maximum allowed tokens on the node!"
);
uint nodeBalance = getEtnyTokens(nodeAddress);
require(
nodeBalance == 0,
"EtnyStaking: Node has ETNY tokens!"
);
}
uint etnyBalance = getEtnyTokens(msg.sender);
require(
etnyBalance - _tokensLockedInStaking[msg.sender] >= amount,
"EtnyStaking: The amount exceeds balance available for staking!"
);
Models.ExtendedStake storage newExtendedReq = _extendedStakeList.push();
newExtendedReq.stakeHolderAddress = msg.sender;
newExtendedReq.rewardAddress = rewardAddress;
newExtendedReq.nodeAddress = nodeAddress;
newExtendedReq.timestamp = block.timestamp;
newExtendedReq.amount = amount;
newExtendedReq.amountBooked = 0;
newExtendedReq.stakingContracts = 0;
newExtendedReq.period = period;
newExtendedReq.operatorRewardPercentage = opReward;
newExtendedReq.allowMultipleOp = allowMultipleOp;
newExtendedReq.autoConfirm = autoConfirm;
newExtendedReq.status = Enums.ExtendedStakeStatus.PENDING;
_extendedStakeId = _extendedStakeList.length - 1;
emit NewExtendedStake(msg.sender, _extendedStakeId);
_stakerExtendedStakeRequests[payable(msg.sender)].push(_extendedStakeId);
if (nodeAddress != address(0)) {
(Models.StakeContract storage stakeContract, uint256 stakeContractID) = addStakeContract(newExtendedReq.stakeHolderAddress, nodeAddress, rewardAddress, period, amount, _extendedStakeId, opReward);
newExtendedReq.stakingContractsStatuses[stakeContract.status] += 1;
newExtendedReq.stakingContractsMapping[newExtendedReq.stakingContracts] = stakeContractID;
newExtendedReq.stakingContracts += 1;
newExtendedReq.amountBooked = amount;
_nodeExtendedStakeRequests[nodeAddress].push(_extendedStakeId);
_nodeExtendedContracts[nodeAddress].push(stakeContractID);
_nodeStakingTotal[nodeAddress] += amount;
}
_tokensLockedInStaking[msg.sender] += amount;
return _extendedStakeId;
}
function addStakeContract(address stakeHolderAddress, address nodeAddress, address rewardAddress, uint16 period, uint64 amount, uint256 stakeId, uint8 opReward) internal returns (Models.StakeContract storage _contract, uint256 stakeContractID){
stakeContractID = _stakingContractsList.length;
Models.StakeContract storage stakeContract = _stakingContractsList.push();
stakeContract.stakeHolder = stakeHolderAddress;
stakeContract.nodeAddress = nodeAddress;
stakeContract.stakeRewardAddress = rewardAddress;
stakeContract.nodeRewardAddress = address(0);
stakeContract.timestamp = block.timestamp;
stakeContract.amount = amount;
stakeContract.period = period;
stakeContract.canceledOn = 0;
stakeContract.expiresOn = 0;
stakeContract.approvedOn = 0;
stakeContract.stakeId = stakeId;
//for base stake should override this value;
stakeContract.status = Enums.StakeContractStatus.PENDING;
stakeContract.stakeType = Enums.StakeType.EXTENDED_STAKE;
stakeContract.operatorRewardPercentage = opReward;
return (
stakeContract,
stakeContractID
);
}
function getExtendedStake(uint256 extendedStakeId)
external
view
returns (
uint256 _baseStakeId,
address stakeHolderAddress,
address rewardAddress,
address nodeAddress,
uint256 timestamp,
uint64 amount,
uint64 amountBooked,
uint64 period,
uint8 operatorReward,
bool allowMultipleOp,
bool autoConfirm,
Enums.ExtendedStakeStatus status,
uint64 stakingContracts
)
{
Models.ExtendedStake storage _stake = _extendedStakeList[
extendedStakeId
];
return (
extendedStakeId,
_stake.stakeHolderAddress,
_stake.rewardAddress,
_stake.nodeAddress,
_stake.timestamp,
_stake.amount,
_stake.amountBooked,
_stake.period,
_stake.operatorRewardPercentage,
_stake.allowMultipleOp,
_stake.autoConfirm,
_stake.status,
_stake.stakingContracts
);
}
function getExtendedStakeRequestContractStats(uint256 extendedStakeId)
external
view
returns (
uint256 _extendedStakeId,
uint64 allContracts,
uint64 pendingContracts,
uint64 approvedContracts,
uint64 declinedContracts,
uint64 canceledContracts,
uint64 terminatedContracts
)
{
Models.ExtendedStake storage _stake = _extendedStakeList[
extendedStakeId
];
return (
extendedStakeId,
_stake.stakingContracts,
_stake.stakingContractsStatuses[Enums.StakeContractStatus.PENDING],
_stake.stakingContractsStatuses[Enums.StakeContractStatus.APPROVED],
_stake.stakingContractsStatuses[Enums.StakeContractStatus.DECLINED],
_stake.stakingContractsStatuses[Enums.StakeContractStatus.CANCELED],
_stake.stakingContractsStatuses[Enums.StakeContractStatus.TERMINATED]
);
}
function getExtendedStakeRequestTotal() public onlyDelegate view returns (uint256 count){
return _extendedStakeList.length;
}
function approveExtendedStakeContract(uint256 stakeId, uint64 stakeContract, address rewardAddress) public onlyDelegate returns (bool){
require(
stakeId < _extendedStakeList.length,
"EtnyStaking: Invalid Extended Stake ID provided!"
);
Models.ExtendedStake storage _stake = _extendedStakeList[stakeId];
require(
stakeContract < _stake.stakingContracts,
"EtnyStaking: Invalid Stake Contract provided!"
);
if (_stake.nodeAddress != address(0)) {
//if the node was provided only the node operator can approve it
require(
_stake.nodeAddress == msg.sender,
"EtnyStaking: Only operator can approve the contract!"
);
require(
rewardAddress != address(0),
"EtnyStaking: Reward address for operator was not provided!"
);
require(
rewardAddress != msg.sender,
"EtnyStaking: Reward address should be different than the node address!"
);
require(
!_canceledBaseStakeNodes[msg.sender],
"EtnyStaking: The base stake contract on this node was canceled!"
);
}
uint256 _contractId = _stake.stakingContractsMapping[stakeContract];
Models.StakeContract storage _contract = _stakingContractsList[_contractId];
require(
_contract.status == Enums.StakeContractStatus.PENDING,
"EtnyStaking: Only pending staking contracts can be approved!"
);
_stake.stakingContractsStatuses[_contract.status] -= 1;
_contract.status = Enums.StakeContractStatus.APPROVED;
_contract.approvedOn = block.timestamp;
_stake.stakingContractsStatuses[_contract.status] += 1;
if (_stake.nodeAddress != address(0))
{
_contract.nodeRewardAddress = rewardAddress;
_stake.amountBooked = _stake.amount;
_stake.status = Enums.ExtendedStakeStatus.APPROVED;
}
if (_stake.amountBooked == _stake.amount
&& _stake.stakingContractsStatuses[Enums.StakeContractStatus.PENDING] == 0) {
_stake.status = Enums.ExtendedStakeStatus.APPROVED;
}
emit ExtendedStakeContractApproved(_contractId, stakeId);
//_nodeStakingTotal[_contract.nodeAddress] += _contract.amount;
return true;
}
function cancelExtendedStakeRequest(uint256 extendedStakeID) public onlyDelegate override returns (bool){
require(
extendedStakeID < _extendedStakeList.length,
"EtnyStaking: Invalid Extended Stake ID provided!"
);
Models.ExtendedStake storage _stake = _extendedStakeList[extendedStakeID];
require(
msg.sender == _stake.stakeHolderAddress,
"EtnyStaking: Only staker can cancel this request!"
);
require(
_stake.status == Enums.ExtendedStakeStatus.PENDING ||
_stake.status == Enums.ExtendedStakeStatus.APPROVED,
"EtnyStaking: Extended stake pool cannot be canceled. It has different status!"
);
_stake.status = Enums.ExtendedStakeStatus.CANCELED;
emit ExtendedStakeCanceled(extendedStakeID);
for (uint64 stakeContract = 0; stakeContract < _stake.stakingContracts; stakeContract++) {
uint256 _contractId = _stake.stakingContractsMapping[stakeContract];
Models.StakeContract storage _contract = _stakingContractsList[_contractId];
_stake.stakingContractsStatuses[_contract.status] -= 1;
if (_contract.status == Enums.StakeContractStatus.PENDING)
{
_contract.status = Enums.StakeContractStatus.TERMINATED;
_contract.canceledOn = block.timestamp;
_contract.expiresOn = block.timestamp;
emit ExtendedStakeContractTerminated(_contractId, _contract.stakeId);
_stake.amountBooked -= _contract.amount;
_nodeStakingTotal[_contract.nodeAddress] -= _contract.amount;
}
else if (_contract.status == Enums.StakeContractStatus.APPROVED)
{
_contract.status = Enums.StakeContractStatus.CANCELED;
_contract.canceledOn = block.timestamp;
_contract.expiresOn = Utils.computeExpirationDate(_contract.period, _contract.approvedOn);
emit ExtendedStakeContractCanceled(_contractId, _contract.stakeId);
}
_stake.stakingContractsStatuses[_contract.status] += 1;
}
if (_stake.amount - _stake.amountBooked > 0)
{
_tokensLockedInStaking[msg.sender] -= (_stake.amount - _stake.amountBooked);
_stake.amount = _stake.amountBooked;
}
return true;
}
///@notice only node operator can decline an Extended Stake Request when he is set into request
function declineExtendedStakeContract(uint256 stakeId, uint64 stakeContract) public onlyDelegate returns (bool){
require(
stakeId < _extendedStakeList.length,
"EtnyStaking: Invalid Extended Stake ID provided!"
);
Models.ExtendedStake storage _stake = _extendedStakeList[stakeId];
require(
stakeContract < _stake.stakingContracts,
"EtnyStaking: Invalid Stake Contract provided!"
);
/* require(
_stake.status == Enums.ExtendedStakeStatus.PENDING,
"EtnyStaking: Stake is having different status!"
);*/
uint256 _contractId = _stake.stakingContractsMapping[stakeContract];
Models.StakeContract storage _contract = _stakingContractsList[_contractId];
require(
_contract.status == Enums.StakeContractStatus.PENDING,
"EtnyStaking: Only pending staking contracts can be declined!"
);
/* require(
msg.sender == _contract.nodeAddress,
"EtnyStaking: Only node operator can decline the contract!"
);
*/
_stake.stakingContractsStatuses[_contract.status] -= 1;
_contract.status = Enums.StakeContractStatus.DECLINED;
_stake.stakingContractsStatuses[_contract.status] += 1;
_stake.amountBooked -= _contract.amount;
_nodeStakingTotal[_contract.nodeAddress] -= _contract.amount;
if (_stake.nodeAddress != address(0)) {
_stake.status = Enums.ExtendedStakeStatus.DECLINED;
_tokensLockedInStaking[_contract.stakeHolder] -= _contract.amount;
}
emit ExtendedStakeContractDeclined(_contractId, stakeId);
return true;
}
///@notice only staker can cancel an Extended Stake Contract when he is set into request
function cancelExtendedStakeContract(uint256 stakeId, uint64 stakeContract, bool isOperatorPerformingBad) public onlyDelegate returns (bool){
require(
stakeId < _extendedStakeList.length,
"EtnyStaking: Invalid Extended Stake ID provided!"
);
Models.ExtendedStake storage _stake = _extendedStakeList[stakeId];
require(
stakeContract < _stake.stakingContracts,
"EtnyStaking: Invalid Stake Contract provided!"
);
/* require(
_stake.status == Enums.ExtendedStakeStatus.PENDING || _stake.status,
"EtnyStaking: Stake is having different status!"
);
*/
uint256 _contractId = _stake.stakingContractsMapping[stakeContract];
Models.StakeContract storage _contract = _stakingContractsList[_contractId];
return _cancelExtendedStakeContract(_stake, _contract, _contractId, isOperatorPerformingBad);
}
function _cancelExtendedStakeContract(Models.ExtendedStake storage _stake, Models.StakeContract storage _contract, uint256 _contractId, bool isOperatorPerformingBad) internal onlyDelegate returns (bool){
require(
_contract.status == Enums.StakeContractStatus.PENDING || _contract.status == Enums.StakeContractStatus.APPROVED,
"EtnyStaking: Only pending or approved staking contracts can be canceled!"
);
require(
msg.sender == _contract.stakeHolder || msg.sender == _contract.nodeAddress || companyAddresses[msg.sender] == true,
"EtnyStaking: Only stakeholder, node operator or companyaddress can cancel the contract!"
);
_stake.stakingContractsStatuses[_contract.status] -= 1;
if (_contract.status == Enums.StakeContractStatus.PENDING)
{
_contract.status = Enums.StakeContractStatus.TERMINATED;
_contract.canceledOn = block.timestamp;
_contract.expiresOn = block.timestamp;
emit ExtendedStakeContractTerminated(_contractId, _contract.stakeId);
_stake.amountBooked -= _contract.amount;
_nodeStakingTotal[_contract.nodeAddress] -= _contract.amount;
if (_stake.nodeAddress != address(0)) {
_stake.status = Enums.ExtendedStakeStatus.TERMINATED;
_stake.amountBooked = 0;
_stake.amount = 0;
_tokensLockedInStaking[_contract.stakeHolder] -= _contract.amount;
}
}
else if (_contract.status == Enums.StakeContractStatus.APPROVED)
{
if (companyAddresses[msg.sender] == true) {
_terminateExtendedStakeContractByCompany(_stake, _contract, _contractId);
}
else {
_contract.status = Enums.StakeContractStatus.CANCELED;
_contract.canceledOn = block.timestamp;
_contract.expiresOn = Utils.computeExpirationDate(_contract.period, _contract.approvedOn);
emit ExtendedStakeContractCanceled(_contractId, _contract.stakeId);
}
if (msg.sender == _contract.stakeHolder || companyAddresses[msg.sender] == true) {
_contract.isOperatorPerformingBad = isOperatorPerformingBad;
}
}
_stake.stakingContractsStatuses[_contract.status] += 1;
return true;
}
function _terminateExtendedStakeContractByCompany(Models.ExtendedStake storage _stake, Models.StakeContract storage _contract, uint256 _contractId) internal {
_contract.status = Enums.StakeContractStatus.TERMINATED;
_contract.canceledOn = block.timestamp;
_contract.expiresOn = block.timestamp;
_stake.amountBooked -= _contract.amount;
if(_stake.status == Enums.ExtendedStakeStatus.APPROVED) _stake.status = Enums.ExtendedStakeStatus.PENDING;
_nodeStakingTotal[_contract.nodeAddress] -= _contract.amount;
emit ExtendedStakeContractTerminated(_contractId, _contract.stakeId);
if (_stake.nodeAddress != address(0)) {
_stake.status = Enums.ExtendedStakeStatus.TERMINATED;
_stake.amountBooked = 0;
_stake.amount = 0;
_tokensLockedInStaking[_contract.stakeHolder] -= _contract.amount;
emit ExtendedStakeTerminated(_contract.stakeId);
}
}
function applyExtendedStakeRequest(uint256 extendedStakeID, uint64 amount, address rewardAddress) public onlyDelegate override returns (bool){
require(
extendedStakeID < _extendedStakeList.length,
"EtnyStaking: Invalid Extended Stake ID provided!"
);
require(
rewardAddress != address(0),
"EtnyStaking: Reward address is the zero address!"
);
require(
rewardAddress != msg.sender,
"EtnyStaking: Reward address must be different than node address!"
);
require(
amount >= minExtendedStakeAmount,
"EtnyStaking: The amount is lower than min extended stake value!"
);
require(
!_canceledBaseStakeNodes[msg.sender],
"EtnyStaking: The base stake contract on this node was canceled!"
);
Models.ExtendedStake storage _stake = _extendedStakeList[extendedStakeID];
require(
_stake.status == Enums.ExtendedStakeStatus.PENDING,
"EtnyStaking: Stake is having different status!"
);
require(
msg.sender != _stake.nodeAddress,
"EtnyStaking: You cannot apply to this Stake Request!"
);
require(
amount + _stake.amountBooked <= _stake.amount,
"EtnyStaking: The amount exceeds the available amount in current stake!"
);
require(
(_stake.stakingContracts <= 1 && !_stake.allowMultipleOp) || _stake.allowMultipleOp,
"EtnyStaking: This stake can accept only 1 contract!"
);
require(
_nodeStakingTotal[msg.sender] > 0,
"EtnyStaking: Need to have at least one base stake setup!"
);
require(
_nodeStakingTotal[msg.sender] + amount <= maxTokens,
"EtnyStaking: The amount exceeds the total of 75000!"
);
if (_stake.allowMultipleOp == false) {
require(
_stake.amount == amount,
"EtnyStaking: This staking pool cannot be split!"
);
}
_stake.amountBooked += amount;
if (_stake.amountBooked == _stake.amount && _stake.autoConfirm)
_stake.status = Enums.ExtendedStakeStatus.APPROVED;
(Models.StakeContract storage stakeContract, uint256 stakeContractID) = addStakeContract(_stake.stakeHolderAddress, msg.sender, _stake.rewardAddress, _stake.period, amount, extendedStakeID, _stake.operatorRewardPercentage);
stakeContract.nodeRewardAddress = rewardAddress;
if (_stake.autoConfirm)
{
stakeContract.status = Enums.StakeContractStatus.APPROVED;
stakeContract.approvedOn = block.timestamp;
}
_stake.stakingContractsStatuses[stakeContract.status] += 1;
_stake.stakingContractsMapping[_stake.stakingContracts] = stakeContractID;
_stake.stakingContracts += 1;
_nodeExtendedContracts[msg.sender].push(stakeContractID);
_nodeExtendedStakeRequests[payable(msg.sender)].push(extendedStakeID);
_nodeStakingTotal[stakeContract.nodeAddress] += stakeContract.amount;
emit NodeAppliedToExtendedStake(stakeContract.nodeAddress, extendedStakeID, _nodeStakingTotal[stakeContract.nodeAddress]);
return true;
}
function freeExtendedStakeRequest(uint256 stakeId) public onlyDelegate override returns (bool){
require(
stakeId < _extendedStakeList.length,
"EtnyStaking: Invalid Extended Stake ID provided!"
);
Models.ExtendedStake storage _stake = _extendedStakeList[stakeId];
require(
msg.sender == _stake.stakeHolderAddress,
"EtnyStaking: Only staker can call this!"
);
require(
_stake.status == Enums.ExtendedStakeStatus.PENDING
|| _stake.status == Enums.ExtendedStakeStatus.CANCELED,
"EtnyStaking: Stake is having different status!"
);
if (_stake.status == Enums.ExtendedStakeStatus.CANCELED) {
require(
_stake.stakingContracts > 0,
"EtnyStaking: Stake has no tokens locked!"
);
}
require(
_stake.amount > _stake.amountBooked,
"EtnyStaking: There are no tokens to unlock!"
);
_tokensLockedInStaking[msg.sender] -= (_stake.amount - _stake.amountBooked);
_stake.amount = _stake.amountBooked;
if (_stake.amount == 0 && _stake.status == Enums.ExtendedStakeStatus.PENDING) {
_stake.status = Enums.ExtendedStakeStatus.CANCELED;
} else {
_stake.status = Enums.ExtendedStakeStatus.APPROVED;
}
emit ExtendedStakeFreed(stakeId, _tokensLockedInStaking[msg.sender]);
return true;
}
function getStakeContractForStake(uint256 stakeId, uint64 stakeContract)
external
view
returns (
uint256 _stakeId,
uint64 _stakeContract,
uint256 stakeContractId,
address stakeHolderAddress,
address nodeAddress,
uint256 timestamp,
uint64 amount,
uint64 period,
Enums.StakeContractStatus status,
uint256 estimatedExpiration
)
{
require(
stakeId < _extendedStakeList.length,
"EtnyStaking: Invalid Extended Stake ID provided!"
);
Models.ExtendedStake storage _stake = _extendedStakeList[stakeId];
require(
stakeContract < _stake.stakingContracts,
"EtnyStaking: Invalid Stake Contract provided!"
);
uint256 _contractId = _stake.stakingContractsMapping[stakeContract];
Models.StakeContract storage _contract = _stakingContractsList[_contractId];
estimatedExpiration = 0;
if (_contract.status == Enums.StakeContractStatus.APPROVED)
estimatedExpiration = Utils.computeExpirationDate(_contract.period, _contract.approvedOn);
else
estimatedExpiration = _contract.expiresOn;
return (
stakeId,
stakeContract,
_contractId,
_stake.stakeHolderAddress,
_contract.nodeAddress,
_contract.timestamp,
_contract.amount,
_contract.period,
_contract.status,
estimatedExpiration
);
}
function getStakeContractForBaseStake(uint256 stakeId, uint64 stakeContract)
external
view
returns (
uint256 _stakeId,
uint64 _stakeContract,
uint256 stakeContractId,
address stakeHolderAddress,
address nodeAddress,
address nodeRewardAddress,
uint256 timestamp,
uint64 amount,
uint64 period,
Enums.StakeContractStatus status,
uint256 expiresOn
)
{
require(
stakeId < _baseStakesList.length,
"EtnyStaking: Invalid Base Stake ID provided!"
);
Models.BaseStake storage _stake = _baseStakesList[stakeId];
require(
stakeContract == 0,
"EtnyStaking: Invalid Stake Contract provided!"
);
uint256 _contractId = _stake.stakeContractId;
Models.StakeContract storage _contract = _stakingContractsList[_contractId];
return (
stakeId,
stakeContract,
_contractId,
_stake.stakeHolderAddress,
_contract.nodeAddress,
_contract.nodeRewardAddress,
_contract.timestamp,
_contract.amount,
_contract.period,
_contract.status,
_contract.expiresOn
);
}
function getStakeContractsTotal() public onlyDelegate view returns (uint256 count){
return _stakingContractsList.length;
}
function getStakeContract(uint256 stakeContractId)
external
view
returns (
uint256 estimatedExpiration,
address stakeHolderAddress,
address nodeAddress,
address nodeRewardAddress,
address stakeHolderRewardAddress,
uint256 timestamp,
uint64 amount,
uint64 opReward,
uint64 period,
Enums.StakeContractStatus status,
Enums.StakeType stakeType
)
{
require(
stakeContractId < _stakingContractsList.length,
"EtnyStaking: Invalid Stake contract ID provided!"
);
Models.StakeContract storage _contract = _stakingContractsList[stakeContractId];
estimatedExpiration = 0;
if (_contract.status == Enums.StakeContractStatus.APPROVED)
estimatedExpiration = Utils.computeExpirationDate(_contract.period, _contract.approvedOn);
else
estimatedExpiration = _contract.expiresOn;
return (
estimatedExpiration,
_contract.stakeHolder,
_contract.nodeAddress,
_contract.nodeRewardAddress,
_contract.stakeRewardAddress,
_contract.timestamp,
_contract.amount,
_contract.operatorRewardPercentage,
_contract.period,
_contract.status,
_contract.stakeType
);
}
function getLockedBalanceAtStake() external view returns (uint256){
return _tokensLockedInStaking[msg.sender];
}
function setLockedBalanceAtStake(address wallet, uint64 amount) external onlyDelegate returns (bool){
require(companyAddresses[msg.sender] == true, "EtnyStaking: Only a company address can perform this action!");
_tokensLockedInStaking[wallet] = amount;
return true;
}
function setStakePending(uint256 stakeId) external onlyDelegate returns (bool){
require(companyAddresses[msg.sender] == true, "EtnyStaking: Only a company address can perform this action!");
Models.ExtendedStake storage _stake = _extendedStakeList[stakeId];
_stake.status = Enums.ExtendedStakeStatus.PENDING;
return true;
}
function getLockedBalanceAtStakeInWei(address wallet) override external view returns (uint256){
uint decimals = 18;
uint value = 10 ** uint(decimals);
return _tokensLockedInStaking[wallet] * value;
}
function getBaseStakeRequestsForNode() public onlyDelegate view returns (uint256[] memory){
return _nodeBaseStakeRequests[msg.sender];
}
function getExtendedStakeRequestsForNode() public onlyDelegate view returns (uint256[] memory){
return _nodeExtendedStakeRequests[msg.sender];
}
function getTotalStakedOnNode() public onlyDelegate view returns (uint256){
return _nodeStakingTotal[msg.sender];
}
function isNode() public onlyDelegate view returns (bool){
return _nodeStakingTotal[msg.sender] > 0;
}
function getBaseStakeRequestsForStakerCount() public onlyDelegate view returns (uint256){
return _stakerBaseStakeRequests[msg.sender].length;
}
function getBaseStakeRequestIdForStaker(uint256 stakeIndex) public onlyDelegate view returns (uint256){
require(
stakeIndex < _stakerBaseStakeRequests[msg.sender].length,
"EtnyStaking: Invalid Index provided!"
);
return _stakerBaseStakeRequests[msg.sender][stakeIndex];
}
function getExtendedStakeRequestsForStakerCount() public onlyDelegate view returns (uint256){
return _stakerExtendedStakeRequests[msg.sender].length;
}
function getExtendedStakeRequestIdForStaker(uint256 stakeIndex) public onlyDelegate view returns (uint256){
require(
stakeIndex < _stakerExtendedStakeRequests[msg.sender].length,
"EtnyStaking: Invalid Index provided!"
);
return _stakerExtendedStakeRequests[msg.sender][stakeIndex];
}
function getBaseStakeRequestsForOperatorCount() public onlyDelegate view returns (uint256){
return _nodeBaseStakeRequests[msg.sender].length;
}
function getBaseStakeRequestIdForOperator(uint256 stakeIndex) public onlyDelegate view returns (uint256){
require(
stakeIndex < _nodeBaseStakeRequests[msg.sender].length,
"EtnyStaking: Invalid Index provided!"
);
return _nodeBaseStakeRequests[msg.sender][stakeIndex];
}
function getExtendedStakeRequestsForOperatorCount() public onlyDelegate view returns (uint256){
return _nodeExtendedStakeRequests[msg.sender].length;
}
function getExtendedStakeRequestIdForOperator(uint256 stakeIndex) public onlyDelegate view returns (uint256){
require(
stakeIndex < _nodeExtendedStakeRequests[msg.sender].length,
"EtnyStaking: Invalid Index provided!"
);
return _nodeExtendedStakeRequests[msg.sender][stakeIndex];
}
function getEtnyTokens(address adr) internal view returns (uint256){
uint decimals = 18;
uint value = 10 ** uint(decimals);
return ERC20Interface(_etnyTokenSmartContractAddress).balanceOf(adr) / value;
}
function getAvailableTokensForStake() public onlyDelegate view returns (uint256){
uint etnyTokens = getEtnyTokens(msg.sender);
return etnyTokens - _tokensLockedInStaking[msg.sender];
}
function isEtnyContractSetup() public onlyDelegate view returns (bool){
return _etnyTokenSmartContractAddress != address(0);
}
function terminateContract(uint256 contractId, bool hasPenalties) public onlyDelegate returns (bool){
require(companyAddresses[msg.sender] == true, "EtnyStaking: Only a company address can terminate a Base Stake Contract and apply penalties!");
require(contractId < _stakingContractsList.length, "EtnyStaking: Invalid Index provided!");
Models.StakeContract storage _contract = _stakingContractsList[contractId];
require(_contract.status == Enums.StakeContractStatus.CANCELED, "EtnyStaking: Only a canceled contract can be ended!");
require(_contract.expiresOn < block.timestamp, "EtnyStaking: The contract can be terminated after it expires.");
if (_contract.stakeType == Enums.StakeType.EXTENDED_STAKE) {
terminateExpiredExtendedStakeContractByJob(contractId);
} else {
terminateExpiredBaseStakeContractByJob(contractId, hasPenalties, true);
}
return true;
}
function getContractDateDetails(uint256 contractId) public view onlyDelegate returns (
uint256 timestamp,
uint256 approvedOn,
uint256 expiresOn,
uint256 estimatedExpiration,
uint256 canceledOn){
require(
contractId < _stakingContractsList.length,
"EtnyStaking: Invalid Index provided!"
);
Models.StakeContract storage _contract = _stakingContractsList[contractId];
estimatedExpiration = 0;
if (_contract.status == Enums.StakeContractStatus.APPROVED)
estimatedExpiration = Utils.computeExpirationDate(_contract.period, _contract.approvedOn);
else
estimatedExpiration = _contract.expiresOn;
return (
_contract.timestamp,
_contract.approvedOn,
_contract.expiresOn,
estimatedExpiration,
_contract.canceledOn
);
}
function terminateExtendPoolContracts(uint256 extendPoolId) public onlyDelegate returns (bool){
require(
extendPoolId < _extendedStakeList.length,
"EtnyStaking: Invalid Index provided!"
);
Models.ExtendedStake storage _stake = _extendedStakeList[extendPoolId];
for (uint64 stakeContract = 0; stakeContract < _stake.stakingContracts; stakeContract++) {
//uint256 _contractId = _stake.stakingContractsMapping[stakeContract];
Models.StakeContract storage _contract = _stakingContractsList[_stake.stakingContractsMapping[stakeContract]];
if (_contract.status == Enums.StakeContractStatus.CANCELED && _contract.expiresOn < block.timestamp) {
_stake.stakingContractsStatuses[_contract.status] -= 1;
_contract.status = Enums.StakeContractStatus.TERMINATED;
_stake.stakingContractsStatuses[_contract.status] += 1;
_tokensLockedInStaking[_contract.stakeHolder] -= _contract.amount;
_nodeStakingTotal[_contract.nodeAddress] -= _contract.amount;
//_stake.amountBooked -= _contract.amount;
//_stake.amount -= _contract.amount;
}
}
if (_stake.stakingContractsStatuses[Enums.StakeContractStatus.CANCELED] == 0
&& _stake.stakingContractsStatuses[Enums.StakeContractStatus.APPROVED] == 0
&& _stake.stakingContractsStatuses[Enums.StakeContractStatus.PENDING] == 0
&& _stake.amount - _stake.amountBooked == 0)
_stake.status = Enums.ExtendedStakeStatus.TERMINATED;
return true;
}
function getExtendPoolMaxExpirationdate(uint256 extendPoolId) public onlyDelegate view returns (uint256){
require(
extendPoolId < _extendedStakeList.length,
"EtnyStaking: Invalid Index provided!"
);
Models.ExtendedStake storage _stake = _extendedStakeList[extendPoolId];
uint256 result = 0;
for (uint64 stakeContract = 0; stakeContract < _stake.stakingContracts; stakeContract++) {
//uint256 _contractId = _stake.stakingContractsMapping[stakeContract];
Models.StakeContract storage _contract = _stakingContractsList[_stake.stakingContractsMapping[stakeContract]];
uint256 estimatedExpiration = 0;
if (_contract.status == Enums.StakeContractStatus.APPROVED)
estimatedExpiration = Utils.computeExpirationDate(_contract.period, _contract.approvedOn);
else
estimatedExpiration = _contract.expiresOn;
if (result < estimatedExpiration)
result = estimatedExpiration;
}
return result;
}
function terminateBaseStake(uint256 baseStakePoolId) public onlyDelegate returns (bool){
require(
baseStakePoolId < _baseStakesList.length,
"EtnyStaking: Invalid Base Stake ID provided!"
);
Models.BaseStake storage _stake = _baseStakesList[baseStakePoolId];
require(
_stake.status == Enums.BaseStakeStatus.CANCELED,
"EtnyStaking: Stake is having different status!"
);
Models.StakeContract storage _contract = _stakingContractsList[_stake.stakeContractId];
require(
_contract.expiresOn < block.timestamp,
"EtnyStaking: Stake is not expired yet!"
);
_stake.status = Enums.BaseStakeStatus.TERMINATED;
_contract.status = Enums.StakeContractStatus.TERMINATED;
_tokensLockedInStaking[_contract.stakeHolder] -= _contract.amount;
_nodeActiveBaseStake[_contract.nodeAddress] = false;
_nodeStakingTotal[_contract.nodeAddress] -= _contract.amount;
_canceledBaseStakeNodes[_contract.nodeAddress] = false;
return true;
}
function updateStakeContractNodeRewardAddress(uint256 contractId, address oldRewardAddress, address newRewardAddress) public onlyDelegate onlyCompanyWallet returns (bool){
require(
contractId < _stakingContractsList.length,
"EtnyStaking: Invalid Index provided!"
);
Models.StakeContract storage _contract = _stakingContractsList[contractId];
require(
oldRewardAddress == _contract.nodeRewardAddress,
"EtnyStaking: reward address provided!"
);
_contract.nodeRewardAddress = newRewardAddress;
return true;
}
function setEtnyTokenSmartContractAddress(address newValue) public onlyDelegate onlyCompanyWallet {
_etnyTokenSmartContractAddress = newValue;
}
function getEtnyTokenSmartContractAddress() public onlyDelegate view returns (address){
return _etnyTokenSmartContractAddress;
}
function getMinExtendedStakeAmount() public onlyDelegate view returns (uint64){
return minExtendedStakeAmount;
}
function setMaxTokens(uint256 newValue) public onlyDelegate onlyCompanyWallet {
maxTokens = newValue;
}
function getMaxTokensOnNode() public onlyDelegate view returns (uint256){
return maxTokens;
}
function setNFTMaxTokens(uint256 newValue) public onlyDelegate onlyCompanyWallet {
maxNFTTokens = newValue;
}
function setMinExtendedStakeAmount(uint64 newValue) public onlyDelegate onlyCompanyWallet {
minExtendedStakeAmount = newValue;
}
function setApyPercentage(uint8 value) public onlyDelegate onlyCompanyWallet {
minPeriodStakeContractInMonths = value;
}
function getMinPeriodForStake() public onlyDelegate view returns (uint8) {
return minPeriodStakeContractInMonths;
}
function setMinPeriodForBaseStake(uint8 value) public onlyDelegate onlyCompanyWallet {
apyPercentage = value;
}
function getCurrentApyPercentage() public onlyDelegate view returns (uint8) {
return apyPercentage;
}
function getStakeTotalSupply() public onlyDelegate view returns (uint64) {
return totalSupply;
}
function getMinBaseStakeAmount() public onlyDelegate view returns (uint64){
return minBaseStakeAmount;
}
function setMinAmountForBaseStake(uint64 value) public onlyDelegate onlyCompanyWallet {
minBaseStakeAmount = value;
}
function setMinAmountForBaseStakeNFT(uint64 value) public onlyDelegate onlyCompanyWallet {
minBaseStakeNFTAmount = value;
}
function getMaxBaseStakeAmount() public onlyDelegate view returns (uint64){
return maxBaseStakeAmount;
}
function setMaxAmountForBaseStake(uint64 value) public onlyDelegate onlyCompanyWallet {
maxBaseStakeAmount = value;
}
function getBaseStakesForNode(address nodeAddress) public view returns (uint256[] memory){
return _nodeBaseStakeRequests[nodeAddress];
}
function getNodeDetails(address nodeAddress) public view returns (uint256[] memory baseStakeRequestList, bool activeBaseStake, uint256 totalStaking, bool canceledBaseStake){
return (
_nodeBaseStakeRequests[nodeAddress],
_nodeActiveBaseStake[nodeAddress],
_nodeStakingTotal[nodeAddress],
_canceledBaseStakeNodes[nodeAddress]
);
}
function cleanCanceledBaseStake(address nodeAddress) public onlyDelegate returns (bool){
require(
_canceledBaseStakeNodes[nodeAddress],
"EtnyStaking: Node is not canceled!"
);
require(
_nodeBaseStakeRequests[nodeAddress].length > 0,
"EtnyStaking: Node is not having any base stakes requests!"
);
uint256 lastSakeIndex = _nodeBaseStakeRequests[nodeAddress].length - 1;
uint256 baseStakeId = _nodeBaseStakeRequests[nodeAddress][lastSakeIndex];
Models.BaseStake storage _stake = _baseStakesList[baseStakeId];
require(
_stake.status == Enums.BaseStakeStatus.APPROVED
|| _stake.status == Enums.BaseStakeStatus.TERMINATED,
"EtnyStaking: Cannot execute cleanup on this status!"
);
_canceledBaseStakeNodes[nodeAddress] = false;
return true;
}
/**
* @notice The company opts to forcibly cancel a Base Stake and enforce the associated penalties.
* @dev The Base Stake penalties for the node exceed the Base Stake amount.
* @dev This means that the entire node will be closed and ALL Base Stake tokens will be locked forever.
* @dev This function allows the company address to forcefully cancel a base stake, closing the staking agreement.
* @dev All the Extended Stake Contracts of the assosiated node are terminated.
* @dev Emits a `ApplyPenaltiesToBaseStakeByCompany` event upon successful termination.
*/
function applyPenaltiesToBaseStakeByCompany(uint256 stakeContractId) public onlyDelegate returns (bool) {
require(companyAddresses[msg.sender] == true, "EtnyStaking: Only a company address can terminate a Base Stake and apply penalties!");
// Check if the provided baseStakeId is valid
require(stakeContractId < _stakingContractsList.length, "EtnyStaking: Invalid Base Stake Contract ID provided!");
// Get the associated stake contract
Models.StakeContract storage _contract = _stakingContractsList[stakeContractId];
// Get the base stake associated with the given ID
Models.BaseStake storage _stake = _baseStakesList[_contract.stakeId];
require(_contract.expiresOn < ONEHUNDREDYEARS, "EtnyStaking: The contract was already prolonged forever!");
_finalizeBaseStakeCancellation(_stake);
_cancelAndProlongForeverBaseStakeContract(_contract);
_terminateForcefullyNodeExtendedContracts(_contract);
emit ApplyPenaltiesToBaseStakeByCompany(_nodeStakingTotal[_contract.nodeAddress]);
return true;
}
function setBaseStakeContractExpirationDateAndStatus(uint256 stakeContractId, uint256 expiresOn, uint256 canceledOn, uint status) public onlyDelegate returns (bool){
require(companyAddresses[msg.sender] == true, "EtnyStaking: Only a company address can perform this action!");
// Check if the provided baseStakeId is valid
require(stakeContractId < _stakingContractsList.length, "EtnyStaking: Invalid Base Stake Contract ID provided!");
// Get the associated stake contract
Models.StakeContract storage _contract = _stakingContractsList[stakeContractId];
_contract.status = Enums.StakeContractStatus(status);
_contract.expiresOn = expiresOn;
_contract.canceledOn = canceledOn;
// Get the base stake associated with the given ID
Models.BaseStake storage _stake = _baseStakesList[_contract.stakeId];
_stake.status = Enums.BaseStakeStatus(status);
_canceledBaseStakeNodes[_stake.nodeAddress] = _stake.status == Enums.BaseStakeStatus.CANCELED;
return true;
}
function terminateExpiredBaseStakeContractByJob(uint256 contractId, bool hasPenalties, bool recalculateContractExpiresOn) public onlyDelegate returns (bool) {
require(companyAddresses[msg.sender] == true, "EtnyStaking: Only a company address can terminate a Base Stake Contract and apply penalties!");
require(contractId < _stakingContractsList.length, "EtnyStaking: Invalid Index provided!");
Models.StakeContract storage _contract = _stakingContractsList[contractId];
require(_contract.stakeType == Enums.StakeType.BASE_STAKE, "EtnyStaking: A Base Stake Contract id is expected!");
require(_contract.status == Enums.StakeContractStatus.CANCELED, "EtnyStaking: Only a canceled contract can be ended!");
if (recalculateContractExpiresOn){
_recalculateExpiresOnForBaseStakeContract(_contract);
}
require(_contract.expiresOn < block.timestamp, "EtnyStaking: The contract can be terminated after it expires.");
Models.BaseStake storage _baseStake = _baseStakesList[_contract.stakeId];
_terminateNodeExtendedContracts(_contract);
if (!hasPenalties) {
// no penalties are present
_subtractFromNodeStakingTotal(_contract.nodeAddress, _contract.amount);
_finalizeBaseStakeContractTermination(_contract);
_subtractFromTokensLockedInStaking(_contract.stakeHolder, _baseStake.amount);
_finalizeBaseStakeTermination(_baseStake);
emit BaseStakeContractTerminated(contractId);
return true;
}
// undo-cancel
_contract.canceledOn = 0;
_canceledBaseStakeNodes[_contract.nodeAddress] = false;
// set as approved
_baseStake.status = Enums.BaseStakeStatus.APPROVED;
_contract.status = Enums.StakeContractStatus.APPROVED;
// extend the contract for an additional period.
_contract.expiresOn = Utils.computeExpirationDate(_contract.period, _contract.approvedOn);
emit BaseStakeContractExtendedForPenalties(contractId);
return true;
}
function terminateExpiredExtendedStakeContractByJob(uint256 contractId) public onlyDelegate {
require(companyAddresses[msg.sender] == true, "EtnyStaking: Only a company address can terminate an Extended Stake Contract and apply penalties!");
require(contractId < _stakingContractsList.length, "EtnyStaking: Invalid Index provided!");
Models.StakeContract storage _contract = _stakingContractsList[contractId];
require(_contract.stakeType == Enums.StakeType.EXTENDED_STAKE, "EtnyStaking: An Extended Stake Contract id is expected!");
require(_contract.status == Enums.StakeContractStatus.CANCELED, "EtnyStaking: Only a canceled contract can be ended!");
require(_contract.expiresOn < block.timestamp, "EtnyStaking: The contract can be terminated after it expires.");
_subtractFromTokensLockedInStaking(_contract.stakeHolder, _contract.amount);
_subtractFromNodeStakingTotal(_contract.nodeAddress, _contract.amount);
Models.ExtendedStake storage _extendedStake = _extendedStakeList[_contract.stakeId];
_extendedStake.amountBooked -= _contract.amount;
_changeExtendedStakeContractStatus(_contract, _extendedStake, Enums.StakeContractStatus.TERMINATED);
_recalculateExtendedStakeStatusOnContractChange(_extendedStake);
emit ExtendedStakeContractTerminated(contractId, _contract.stakeId);
}
function _finalizeBaseStakeTermination(Models.BaseStake storage _baseStake) internal {
_baseStake.status = Enums.BaseStakeStatus.TERMINATED;
}
function _finalizeBaseStakeCancellation(Models.BaseStake storage _baseStake) internal {
_baseStake.status = Enums.BaseStakeStatus.CANCELED;
}
function _finalizeBaseStakeContractTermination(Models.StakeContract storage _baseContract) internal {
_baseContract.status = Enums.StakeContractStatus.TERMINATED;
_baseContract.canceledOn = block.timestamp;
_baseContract.expiresOn = block.timestamp;
_canceledBaseStakeNodes[_baseContract.nodeAddress] = false;
_nodeActiveBaseStake[_baseContract.nodeAddress] = false;
}
/*
* Update the contract and keep the tokens locked for a 100 years.
* By keeping the contract ongoing the node will not be functional because we also have to terminate all extended staking contracts
*/
function _cancelAndProlongForeverBaseStakeContract(Models.StakeContract storage _baseContract) internal {
_baseContract.status = Enums.StakeContractStatus.CANCELED;
_baseContract.canceledOn = block.timestamp;
_baseContract.expiresOn = ONEHUNDREDYEARS; // 12.09.2123 TODO ANDREI why not now + one hundred years?
_canceledBaseStakeNodes[_baseContract.nodeAddress] = true;
_nodeActiveBaseStake[_baseContract.nodeAddress] = true;
}
/**
* At this point the Extended Stake Contracts should be either TERMINATED or CANCELLED.
* Here we terminate any remaining CANCELLED contracts.
* The termination doesn't check the expiration date, as the node will receive penalities.
*/
function _terminateForcefullyNodeExtendedContracts(Models.StakeContract storage _baseContract) internal {
for (uint256 i = 0; i < _nodeExtendedContracts[_baseContract.nodeAddress].length; i++) {
uint256 _contractId = _nodeExtendedContracts[_baseContract.nodeAddress][i];
Models.StakeContract storage _extendedContract = _stakingContractsList[_contractId];
Models.ExtendedStake storage _extendedStake = _extendedStakeList[_extendedContract.stakeId];
if (_extendedContract.status == Enums.StakeContractStatus.CANCELED){
_terminateExtendedStakeContractByCompany(_extendedStake, _extendedContract, _contractId);
_extendedContract.isOperatorPerformingBad = true;
} else if (_extendedContract.status == Enums.StakeContractStatus.PENDING || _extendedContract.status == Enums.StakeContractStatus.APPROVED) {
_cancelExtendedStakeContract(_extendedStake, _extendedContract, _contractId, true);
}
}
}
/**
* At this point the Extended Stake Contracts should be either TERMINATED or CANCELLED.
* Here we terminate any remaining CANCELLED contracts that have reached their expiration date.
* A Canceled Extended Stake with amountBooked = 0 means that it is already terminated.
*/
function _terminateNodeExtendedContracts(Models.StakeContract storage _baseContract) internal {
for (uint256 i = 0; i < _nodeExtendedContracts[_baseContract.nodeAddress].length; i++) {
uint256 _contractId = _nodeExtendedContracts[_baseContract.nodeAddress][i];
Models.StakeContract storage _extendedContract = _stakingContractsList[_contractId];
Models.ExtendedStake storage _extendedStake = _extendedStakeList[_extendedContract.stakeId];
if (_extendedContract.status == Enums.StakeContractStatus.CANCELED && _extendedContract.expiresOn < block.timestamp) {
_finalizeExtendedStakeContractTermination(_extendedContract, _extendedStake);
_subtractFromTokensLockedInStaking(_extendedContract.stakeHolder, _extendedContract.amount);
_subtractFromNodeStakingTotal(_extendedContract.nodeAddress, _extendedContract.amount);
_extendedStake.amountBooked -= _extendedContract.amount;
if (_extendedStake.nodeAddress != address(0)) {
// if delegated, we have only one contract and we terminate it
_extendedStake.status = Enums.ExtendedStakeStatus.TERMINATED;
emit ExtendedStakeTerminated(_extendedContract.stakeId);
}
}
_recalculateExtendedStakeStatusOnContractChange(_extendedStake);
}
}
function _finalizeExtendedStakeContractTermination(Models.StakeContract storage _extendedContract, Models.ExtendedStake storage _extendedStake) internal {
_changeExtendedStakeContractStatus(_extendedContract, _extendedStake, Enums.StakeContractStatus.TERMINATED);
_extendedContract.canceledOn = block.timestamp;
_extendedContract.expiresOn = block.timestamp;
}
function _subtractFromNodeStakingTotal(address nodeAddress, uint64 amount) internal {
require (_nodeStakingTotal[nodeAddress] >= amount, "Insufficient node staked tokens for subtraction.");
_nodeStakingTotal[nodeAddress] -= amount;
}
function _subtractFromTokensLockedInStaking(address stakeHolderAddress, uint64 amount) internal {
require (_tokensLockedInStaking[stakeHolderAddress] >= amount, "Insufficient stake holder locked tokens in staking for subtraction.");
_tokensLockedInStaking[stakeHolderAddress] -= amount;
}
/**
* @dev This function is used to update the status of extended stakes when changes occur
* in one of the linked extended staking contracts. It may be called after a linked extended staking
* contract is CANCELLED or TERMINATED to ensure that extended stakes are still valid and meet the updated criteria.
*/
function _recalculateExtendedStakeStatusOnContractChange(Models.ExtendedStake storage _extendedStake) internal {
if (_extendedStake.status == Enums.ExtendedStakeStatus.APPROVED && _extendedStake.amountBooked != _extendedStake.amount) {
_extendedStake.status = Enums.ExtendedStakeStatus.PENDING;
}
}
function _changeExtendedStakeContractStatus(Models.StakeContract storage _extendedContract, Models.ExtendedStake storage _extendedStake, Enums.StakeContractStatus status) internal {
_extendedStake.stakingContractsStatuses[_extendedContract.status] -= 1;
_extendedContract.status = status;
_extendedStake.stakingContractsStatuses[_extendedContract.status] += 1;
}
/**
* @notice Recalculates the expiration date for a Base Stake Contract.
*
* @dev This function updates the expiration date for a specific Base Stake Contract based on
* the linked extended state contracts. It ensures that the expiration
* date accurately reflects the current staking agreement.
*/
function _recalculateExpiresOnForBaseStakeContract(Models.StakeContract storage _contract) internal {
for (uint256 i = 0; i < _nodeExtendedContracts[_contract.nodeAddress].length; i++) {
uint256 _extContractIndex = _nodeExtendedContracts[_contract.nodeAddress][i];
uint256 _extContractExpiresOn = _stakingContractsList[_extContractIndex].expiresOn;
// Update the expiresOn date for the base stake contract
if (_contract.expiresOn < _extContractExpiresOn) {
_contract.expiresOn = _extContractExpiresOn;
}
}
}
/*function redeemTokens() public returns (bool){
uint decimals = 18;
uint amount = 10000 * 10 ** uint(decimals);
uint256 balance = ERC20Interface(_etnyTokenSmartContractAddress).balanceOf(address(this));
require(amount <= balance, "ETNY Staking: insuficient tokens for redeem!");
ERC20Interface(_etnyTokenSmartContractAddress).transfer(msg.sender, amount);
return true;
}
function getBalance() public view returns (uint256){
return getEtnyTokens(address(this));
}
*/
}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"ApplyPenaltiesToBaseStakeByCompany","inputs":[{"type":"uint256","name":"nodeStakingTotal","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"BaseStakeApproved","inputs":[{"type":"uint256","name":"baseStakeId","internalType":"uint256","indexed":false},{"type":"uint256","name":"nodeStakingTotal","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"BaseStakeContractCanceled","inputs":[{"type":"uint256","name":"stakeContractId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"BaseStakeContractExtendedForPenalties","inputs":[{"type":"uint256","name":"contractId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"BaseStakeContractTerminated","inputs":[{"type":"uint256","name":"stakeContractId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExtendedStakeCanceled","inputs":[{"type":"uint256","name":"extendedStakeId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExtendedStakeContractApproved","inputs":[{"type":"uint256","name":"contractId","internalType":"uint256","indexed":false},{"type":"uint256","name":"extendedContractStakeId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExtendedStakeContractCanceled","inputs":[{"type":"uint256","name":"contractId","internalType":"uint256","indexed":false},{"type":"uint256","name":"extendedContractStakeId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExtendedStakeContractDeclined","inputs":[{"type":"uint256","name":"contractId","internalType":"uint256","indexed":false},{"type":"uint256","name":"extendedContractStakeId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExtendedStakeContractTerminated","inputs":[{"type":"uint256","name":"contractId","internalType":"uint256","indexed":false},{"type":"uint256","name":"extendedContractStakeId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExtendedStakeFreed","inputs":[{"type":"uint256","name":"extendedStakeId","internalType":"uint256","indexed":false},{"type":"uint256","name":"tokensLockedInStaking","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExtendedStakeTerminated","inputs":[{"type":"uint256","name":"extendedStakeId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NewBaseStake","inputs":[{"type":"address","name":"staker","internalType":"address","indexed":true},{"type":"uint256","name":"baseStakeId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NewExtendedStake","inputs":[{"type":"address","name":"staker","internalType":"address","indexed":true},{"type":"uint256","name":"baseStakeId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NewStakeContract","inputs":[{"type":"address","name":"staker","internalType":"address","indexed":true},{"type":"address","name":"node","internalType":"address","indexed":true},{"type":"uint256","name":"contractId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NodeAppliedToExtendedStake","inputs":[{"type":"address","name":"node","internalType":"address","indexed":true},{"type":"uint256","name":"extendedStakeId","internalType":"uint256","indexed":false},{"type":"uint256","name":"nodeStakingTotal","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ProxyTransferred","inputs":[{"type":"address","name":"_from","internalType":"address","indexed":true},{"type":"address","name":"_to","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"_owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"_rowNumber","internalType":"uint256"}],"name":"addBaseStakeRequest","inputs":[{"type":"address","name":"nodeAddress","internalType":"address"},{"type":"uint64","name":"amount","internalType":"uint64"},{"type":"uint16","name":"period","internalType":"uint16"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addCompanyWallet","inputs":[{"type":"address","name":"companyAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"_extendedStakeId","internalType":"uint256"}],"name":"addExtendedStakeRequest","inputs":[{"type":"address","name":"nodeAddress","internalType":"address"},{"type":"uint64","name":"amount","internalType":"uint64"},{"type":"address","name":"rewardAddress","internalType":"address"},{"type":"uint16","name":"period","internalType":"uint16"},{"type":"uint8","name":"opReward","internalType":"uint8"},{"type":"bool","name":"allowMultipleOp","internalType":"bool"},{"type":"bool","name":"autoConfirm","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"applyExtendedStakeRequest","inputs":[{"type":"uint256","name":"extendedStakeID","internalType":"uint256"},{"type":"uint64","name":"amount","internalType":"uint64"},{"type":"address","name":"rewardAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"applyPenaltiesToBaseStakeByCompany","inputs":[{"type":"uint256","name":"stakeContractId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approveBaseStakeRequest","inputs":[{"type":"uint256","name":"baseStakeId","internalType":"uint256"},{"type":"address","name":"rewardAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approveExtendedStakeContract","inputs":[{"type":"uint256","name":"stakeId","internalType":"uint256"},{"type":"uint64","name":"stakeContract","internalType":"uint64"},{"type":"address","name":"rewardAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"callerAddress","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"cancelBaseStakeRequest","inputs":[{"type":"uint256","name":"baseStakeId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"cancelExtendedStakeContract","inputs":[{"type":"uint256","name":"stakeId","internalType":"uint256"},{"type":"uint64","name":"stakeContract","internalType":"uint64"},{"type":"bool","name":"isOperatorPerformingBad","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"cancelExtendedStakeRequest","inputs":[{"type":"uint256","name":"extendedStakeID","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"cleanCanceledBaseStake","inputs":[{"type":"address","name":"nodeAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"declineBaseStakeRequest","inputs":[{"type":"uint256","name":"baseStakeId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"declineExtendedStakeContract","inputs":[{"type":"uint256","name":"stakeId","internalType":"uint256"},{"type":"uint64","name":"stakeContract","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"freeExtendedStakeRequest","inputs":[{"type":"uint256","name":"stakeId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getAvailableTokensForStake","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_baseStakeId","internalType":"uint256"},{"type":"address","name":"stakeHolderAddress","internalType":"address"},{"type":"address","name":"rewardAddress","internalType":"address"},{"type":"address","name":"nodeAddress","internalType":"address"},{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint64","name":"amount","internalType":"uint64"},{"type":"uint64","name":"period","internalType":"uint64"},{"type":"uint8","name":"status","internalType":"enum Enums.BaseStakeStatus"},{"type":"uint8","name":"stakeType","internalType":"enum Enums.StakeType"}],"name":"getBaseStake","inputs":[{"type":"uint256","name":"baseStakeId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getBaseStakeRequestIdForOperator","inputs":[{"type":"uint256","name":"stakeIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getBaseStakeRequestIdForStaker","inputs":[{"type":"uint256","name":"stakeIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"count","internalType":"uint256"}],"name":"getBaseStakeRequestTotal","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getBaseStakeRequestsForNode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getBaseStakeRequestsForOperatorCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getBaseStakeRequestsForStakerCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getBaseStakesForNode","inputs":[{"type":"address","name":"nodeAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint256","name":"approvedOn","internalType":"uint256"},{"type":"uint256","name":"expiresOn","internalType":"uint256"},{"type":"uint256","name":"estimatedExpiration","internalType":"uint256"},{"type":"uint256","name":"canceledOn","internalType":"uint256"}],"name":"getContractDateDetails","inputs":[{"type":"uint256","name":"contractId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"getCurrentApyPercentage","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getEtnyTokenSmartContractAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getExtendPoolMaxExpirationdate","inputs":[{"type":"uint256","name":"extendPoolId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_baseStakeId","internalType":"uint256"},{"type":"address","name":"stakeHolderAddress","internalType":"address"},{"type":"address","name":"rewardAddress","internalType":"address"},{"type":"address","name":"nodeAddress","internalType":"address"},{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint64","name":"amount","internalType":"uint64"},{"type":"uint64","name":"amountBooked","internalType":"uint64"},{"type":"uint64","name":"period","internalType":"uint64"},{"type":"uint8","name":"operatorReward","internalType":"uint8"},{"type":"bool","name":"allowMultipleOp","internalType":"bool"},{"type":"bool","name":"autoConfirm","internalType":"bool"},{"type":"uint8","name":"status","internalType":"enum Enums.ExtendedStakeStatus"},{"type":"uint64","name":"stakingContracts","internalType":"uint64"}],"name":"getExtendedStake","inputs":[{"type":"uint256","name":"extendedStakeId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_extendedStakeId","internalType":"uint256"},{"type":"uint64","name":"allContracts","internalType":"uint64"},{"type":"uint64","name":"pendingContracts","internalType":"uint64"},{"type":"uint64","name":"approvedContracts","internalType":"uint64"},{"type":"uint64","name":"declinedContracts","internalType":"uint64"},{"type":"uint64","name":"canceledContracts","internalType":"uint64"},{"type":"uint64","name":"terminatedContracts","internalType":"uint64"}],"name":"getExtendedStakeRequestContractStats","inputs":[{"type":"uint256","name":"extendedStakeId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getExtendedStakeRequestIdForOperator","inputs":[{"type":"uint256","name":"stakeIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getExtendedStakeRequestIdForStaker","inputs":[{"type":"uint256","name":"stakeIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"count","internalType":"uint256"}],"name":"getExtendedStakeRequestTotal","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getExtendedStakeRequestsForNode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getExtendedStakeRequestsForOperatorCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getExtendedStakeRequestsForStakerCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getLockedBalanceAtStake","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getLockedBalanceAtStakeInWei","inputs":[{"type":"address","name":"wallet","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"getMaxBaseStakeAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getMaxTokensOnNode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"getMinBaseStakeAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"getMinExtendedStakeAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"getMinPeriodForStake","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"baseStakeRequestList","internalType":"uint256[]"},{"type":"bool","name":"activeBaseStake","internalType":"bool"},{"type":"uint256","name":"totalStaking","internalType":"uint256"},{"type":"bool","name":"canceledBaseStake","internalType":"bool"}],"name":"getNodeDetails","inputs":[{"type":"address","name":"nodeAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"estimatedExpiration","internalType":"uint256"},{"type":"address","name":"stakeHolderAddress","internalType":"address"},{"type":"address","name":"nodeAddress","internalType":"address"},{"type":"address","name":"nodeRewardAddress","internalType":"address"},{"type":"address","name":"stakeHolderRewardAddress","internalType":"address"},{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint64","name":"amount","internalType":"uint64"},{"type":"uint64","name":"opReward","internalType":"uint64"},{"type":"uint64","name":"period","internalType":"uint64"},{"type":"uint8","name":"status","internalType":"enum Enums.StakeContractStatus"},{"type":"uint8","name":"stakeType","internalType":"enum Enums.StakeType"}],"name":"getStakeContract","inputs":[{"type":"uint256","name":"stakeContractId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_stakeId","internalType":"uint256"},{"type":"uint64","name":"_stakeContract","internalType":"uint64"},{"type":"uint256","name":"stakeContractId","internalType":"uint256"},{"type":"address","name":"stakeHolderAddress","internalType":"address"},{"type":"address","name":"nodeAddress","internalType":"address"},{"type":"address","name":"nodeRewardAddress","internalType":"address"},{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint64","name":"amount","internalType":"uint64"},{"type":"uint64","name":"period","internalType":"uint64"},{"type":"uint8","name":"status","internalType":"enum Enums.StakeContractStatus"},{"type":"uint256","name":"expiresOn","internalType":"uint256"}],"name":"getStakeContractForBaseStake","inputs":[{"type":"uint256","name":"stakeId","internalType":"uint256"},{"type":"uint64","name":"stakeContract","internalType":"uint64"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_stakeId","internalType":"uint256"},{"type":"uint64","name":"_stakeContract","internalType":"uint64"},{"type":"uint256","name":"stakeContractId","internalType":"uint256"},{"type":"address","name":"stakeHolderAddress","internalType":"address"},{"type":"address","name":"nodeAddress","internalType":"address"},{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint64","name":"amount","internalType":"uint64"},{"type":"uint64","name":"period","internalType":"uint64"},{"type":"uint8","name":"status","internalType":"enum Enums.StakeContractStatus"},{"type":"uint256","name":"estimatedExpiration","internalType":"uint256"}],"name":"getStakeContractForStake","inputs":[{"type":"uint256","name":"stakeId","internalType":"uint256"},{"type":"uint64","name":"stakeContract","internalType":"uint64"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"count","internalType":"uint256"}],"name":"getStakeContractsTotal","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"getStakeTotalSupply","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTotalStakedOnNode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"implementation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isEtnyContractSetup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isNode","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"lockBaseStakeRequest","inputs":[{"type":"uint256","name":"baseStakeId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeCompanyWallet","inputs":[{"type":"address","name":"oldCompanyAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setApyPercentage","inputs":[{"type":"uint8","name":"value","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"setBaseStakeContractExpirationDateAndStatus","inputs":[{"type":"uint256","name":"stakeContractId","internalType":"uint256"},{"type":"uint256","name":"expiresOn","internalType":"uint256"},{"type":"uint256","name":"canceledOn","internalType":"uint256"},{"type":"uint256","name":"status","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setEtnyTokenSmartContractAddress","inputs":[{"type":"address","name":"newValue","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"setLockedBalanceAtStake","inputs":[{"type":"address","name":"wallet","internalType":"address"},{"type":"uint64","name":"amount","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxAmountForBaseStake","inputs":[{"type":"uint64","name":"value","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxTokens","inputs":[{"type":"uint256","name":"newValue","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinAmountForBaseStake","inputs":[{"type":"uint64","name":"value","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinAmountForBaseStakeNFT","inputs":[{"type":"uint64","name":"value","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinExtendedStakeAmount","inputs":[{"type":"uint64","name":"newValue","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinPeriodForBaseStake","inputs":[{"type":"uint8","name":"value","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setNFTMaxTokens","inputs":[{"type":"uint256","name":"newValue","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"setStakePending","inputs":[{"type":"uint256","name":"stakeId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"terminateBaseStake","inputs":[{"type":"uint256","name":"baseStakePoolId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"terminateContract","inputs":[{"type":"uint256","name":"contractId","internalType":"uint256"},{"type":"bool","name":"hasPenalties","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"terminateExpiredBaseStakeContractByJob","inputs":[{"type":"uint256","name":"contractId","internalType":"uint256"},{"type":"bool","name":"hasPenalties","internalType":"bool"},{"type":"bool","name":"recalculateContractExpiresOn","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"terminateExpiredExtendedStakeContractByJob","inputs":[{"type":"uint256","name":"contractId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"terminateExtendPoolContracts","inputs":[{"type":"uint256","name":"extendPoolId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferProxy","inputs":[{"type":"address","name":"_newProxy","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"updateStakeContractNodeRewardAddress","inputs":[{"type":"uint256","name":"contractId","internalType":"uint256"},{"type":"address","name":"oldRewardAddress","internalType":"address"},{"type":"address","name":"newRewardAddress","internalType":"address"}]}]
Contract Creation Code
0x6080604052620124f860165562036ee8601755601880546001600160d01b0319167302bc00000000000007b80000000000e4e1c0060a179055601980546001600160c01b03191671138800000000000124f80000000000000bd017905534801561006857600080fd5b506100716100ba565b3360008181526002602052604090208054600160ff1991821681178355600580546001600160a01b031990811686178255845490931690911790925581541690911790556101d1565b600054610100900460ff16806100cf5750303b155b806100dd575060005460ff16155b6101445760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b600054610100900460ff16158015610166576000805461ffff19166101011790555b600080546201000033810262010000600160b01b0319909216919091178083556040519190046001600160a01b031691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156101ce576000805461ff00191690555b50565b61958c806101e06000396000f3fe608060405234801561001057600080fd5b50600436106104695760003560e01c80638caafbff1161024c578063c573a9b611610146578063db797e81116100c3578063ea55e31911610087578063ea55e31914610a42578063f2fde38b14610a6e578063f3b5397414610a81578063f8a25c5614610a94578063faa8aab114610a9c57600080fd5b8063db797e81146109ec578063de7c883014610a01578063e0768b1814610a14578063e8454f0714610a27578063e99edf4114610a3a57600080fd5b8063cd7f0bcc1161010a578063cd7f0bcc146109ae578063cf3c3287146109b6578063d53ce9a9146109be578063d598ed98146109d1578063da67129a146109d957600080fd5b8063c573a9b61461093d578063c6aa90ef14610945578063c756023914610980578063c8f00e7514610993578063c91951c7146109a657600080fd5b8063ab205d08116101d4578063b3036c6411610198578063b3036c64146108dd578063b6b7b3cf146108e5578063b6c4ab71146108ed578063b6ecc1cc14610907578063bafb35811461091a57600080fd5b8063ab205d081461087e578063ac870fe814610891578063af68faae146108a4578063b06ba626146108b7578063b2bdfa7b146108ca57600080fd5b806390cadc5a1161021b57806390cadc5a1461081457806391a8c1c514610827578063946e203f14610850578063a4f8277314610863578063a6f958c81461086b57600080fd5b80638caafbff146107cf5780638cd03f77146107d75780638d2adf32146107ea5780638da5cb5b146107fd57600080fd5b8063458dcf6a1161036857806367e40097116102e55780638014522d116102a95780638014522d1461076457806380605c931461077757806383082bb21461078a57806383c8eed91461079d57806388b4ec28146107c757600080fd5b806367e400971461071b5780636b2963551461072e578063715018a614610741578063749490b8146107495780637c5045e81461075c57600080fd5b80635d0d71661161032c5780635d0d7166146106bd5780635eba1aa3146106e557806362647959146106f8578063676465401461070057806367a53be31461071357600080fd5b8063458dcf6a14610644578063488b8e8b146106575780634d263b611461066a578063512532891461067f5780635c60da1b1461069257600080fd5b806328d9228c116103f657806337daa815116103ba57806337daa815146105ab578063380ae6be1461060357806339ad083d146106165780633b7973ed14610629578063438787d01461063157600080fd5b806328d9228c1461054c57806329e0a52b1461055f57806329e7d373146105725780632e14edaa146105855780633348dccd1461059857600080fd5b806311e776fe1161043d57806311e776fe146104db5780631492794d146104f0578063194dc6c8146105115780631c4bc72914610519578063275fdda51461053957600080fd5b8062226faa1461046e578063033751a2146104965780630b0e33d0146104c05780630ef7ef77146104c8575b600080fd5b61048161047c366004618632565b610aaf565b60405190151581526020015b60405180910390f35b6104a96104a4366004618632565b610bdc565b60405161048d9b9a9998979695949392919061868e565b610481610e37565b6104816104d6366004618737565b610e63565b6104ee6104e9366004618632565b610f66565b005b6105036104fe366004618632565b610fb1565b60405190815260200161048d565b61050361102c565b61052161104d565b6040516001600160401b03909116815260200161048d565b610481610547366004618773565b61107d565b61048161055a3660046187bc565b611214565b61048161056d3660046187ef565b611290565b610481610580366004618632565b6117c4565b6104ee610593366004618822565b611ad4565b6104ee6105a636600461883d565b611b28565b6105be6105b9366004618632565b611b91565b604080519788526001600160401b03968716602089015294861694870194909452918416606086015283166080850152821660a08401521660c082015260e00161048d565b610481610611366004618632565b611c6a565b6104ee610624366004618869565b612253565b6105036122af565b6104ee61063f366004618822565b6122dd565b610503610652366004618822565b61232f565b6104ee61066536600461883d565b61236e565b6106726123e1565b60405161048d91906188c0565b61050361068d366004618632565b61245a565b6003546106a5906001600160a01b031681565b6040516001600160a01b03909116815260200161048d565b6106d06106cb366004618632565b6125f8565b60405161048d999897969594939291906188d3565b6104816106f3366004618632565b612777565b610503612991565b6104ee61070e366004618632565b6129bf565b610481612cca565b610503610729366004618632565b612cfa565b61048161073c366004618822565b612d63565b6104ee612fdf565b6104816107573660046187ef565b613060565b610503613884565b610481610772366004618632565b6138b2565b6104ee610785366004618869565b613c25565b610481610798366004618632565b613c87565b6107b06107ab366004618943565b614604565b60405161048d9b9a99989796959493929190618966565b610503614777565b6105216147a5565b6104816107e5366004618632565b6147cf565b6104ee6107f836600461883d565b6149af565b6000546201000090046001600160a01b03166106a5565b6104ee610822366004618822565b614a22565b61083a610835366004618943565b614a73565b60405161048d9a999897969594939291906189e0565b61048161085e366004618943565b614cb6565b610503615031565b610481610879366004618a4f565b615052565b61048161088c366004618632565b615188565b6104ee61089f366004618822565b615217565b6105036108b2366004618a84565b61527f565b6105036108c5366004618abe565b615807565b6005546106a5906001600160a01b031681565b61067261618f565b610521616206565b6108f5616237565b60405160ff909116815260200161048d565b6104ee61091536600461883d565b61625b565b61092d610928366004618822565b6162ce565b60405161048d9493929190618b44565b61050361636e565b610958610953366004618632565b61638f565b604080519586526020860194909452928401919091526060830152608082015260a00161048d565b61050361098e366004618632565b6164db565b6104816109a1366004618632565b616544565b6105036167b1565b6106a56167d2565b6108f56167fc565b6104816109cc366004618b75565b616825565b610503616bf3565b6104816109e7366004618b9a565b616c21565b33600090815260146020526040902054610503565b610672610a0f366004618822565b616ef3565b6104ee610a22366004618632565b616f5f565b610503610a35366004618632565b616faa565b610521617013565b610a55610a50366004618632565b617044565b60405161048d9d9c9b9a99989796959493929190618bbd565b6104ee610a7c366004618822565b6171a0565b610481610a8f366004618c5d565b61729e565b6105036173c6565b6001546106a5906001600160a01b031681565b3360009081526002602052604081205460ff16610ae75760405162461bcd60e51b8152600401610ade90618c82565b60405180910390fd5b6009548210610b085760405162461bcd60e51b8152600401610ade90618cd4565b600060098381548110610b1d57610b1d618d20565b6000918252602090912060069091020190506001600482810154600160501b900460ff1690811115610b5157610b5161864b565b14610b6e5760405162461bcd60e51b8152600401610ade90618d36565b60048101805460ff60501b1916600360501b1790556005810154600b8054600092908110610b9e57610b9e618d20565b600091825260209091206009600c90920201908101805460ff1916600317905542600682015564012117d1576008909101555060019150505b919050565b6000806000806000806000806000806000600b805490508c10610c5a5760405162461bcd60e51b815260206004820152603060248201527f45746e795374616b696e673a20496e76616c6964205374616b6520636f6e747260448201526f6163742049442070726f76696465642160801b6064820152608401610ade565b6000600b8d81548110610c6f57610c6f618d20565b600091825260208220919d50600c020190506001600982015460ff166004811115610c9c57610c9c61864b565b03610d35576005810154600782015460405163d83102cd60e01b8152600160801b90920461ffff16600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af4158015610d0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2e9190618d84565b9b50610d3d565b80600801549b505b8b8160000160009054906101000a90046001600160a01b03168260020160009054906101000a90046001600160a01b03168360030160009054906101000a90046001600160a01b03168460010160009054906101000a90046001600160a01b031685600401548660050160009054906101000a90046001600160401b03168760050160089054906101000a90046001600160401b03168860050160109054906101000a900461ffff168960090160009054906101000a900460ff168a600b0160009054906101000a900460ff168261ffff1692509b509b509b509b509b509b509b509b509b509b509b505091939597999b90929496989a50565b6001546000906001600160a01b03163314610e5157600080fd5b506007546001600160a01b0316151590565b6001546000906001600160a01b03163314610e7d57600080fd5b600a548410610e9e5760405162461bcd60e51b8152600401610ade90618d9d565b6000600a8581548110610eb357610eb3618d20565b906000526020600020906007020190508060040160109054906101000a90046001600160401b03166001600160401b0316846001600160401b031610610f0b5760405162461bcd60e51b8152600401610ade90618ded565b6001600160401b0384166000908152600582016020526040812054600b805491929183908110610f3d57610f3d618d20565b90600052602060002090600c02019050610f598382848861740e565b93505050505b9392505050565b6001546001600160a01b03163314610f7d57600080fd5b3360009081526002602052604090205460ff16610fac5760405162461bcd60e51b8152600401610ade90618c82565b601655565b6001546000906001600160a01b03163314610fcb57600080fd5b336000908152600c60205260409020548210610ff95760405162461bcd60e51b8152600401610ade90618e3a565b336000908152600c6020526040902080548390811061101a5761101a618d20565b90600052602060002001549050919050565b6001546000906001600160a01b0316331461104657600080fd5b5060095490565b6001546000906001600160a01b0316331461106757600080fd5b506018546201000090046001600160401b031690565b6001546000906001600160a01b0316331461109757600080fd5b3360009081526002602052604090205460ff1615156001146110cb5760405162461bcd60e51b8152600401610ade90618e7e565b600b5485106110ec5760405162461bcd60e51b8152600401610ade90618ec9565b6000600b868154811061110157611101618d20565b90600052602060002090600c020190508260048111156111235761112361864b565b60098201805460ff191660018360048111156111415761114161864b565b02179055506008810185905560068101849055600a8101546009805460009290811061116f5761116f618d20565b906000526020600020906006020190508360048111156111915761119161864b565b81600401600a6101000a81548160ff021916908360048111156111b6576111b661864b565b02179055506003600482810154600160501b900460ff16908111156111dd576111dd61864b565b6002909201546001600160a01b03166000908152601560205260409020805460ff1916919092141790555060019050949350505050565b6001546000906001600160a01b0316331461122e57600080fd5b3360009081526002602052604090205460ff1615156001146112625760405162461bcd60e51b8152600401610ade90618e7e565b506001600160a01b03821660009081526014602052604090206001600160401b038216905560015b92915050565b6001546000906001600160a01b031633146112aa57600080fd5b600a5484106112cb5760405162461bcd60e51b8152600401610ade90618d9d565b6000600a85815481106112e0576112e0618d20565b906000526020600020906007020190508060040160109054906101000a90046001600160401b03166001600160401b0316846001600160401b0316106113385760405162461bcd60e51b8152600401610ade90618ded565b60028101546001600160a01b0316156114fd5760028101546001600160a01b031633146113c45760405162461bcd60e51b815260206004820152603460248201527f45746e795374616b696e673a204f6e6c79206f70657261746f722063616e20616044820152737070726f76652074686520636f6e74726163742160601b6064820152608401610ade565b6001600160a01b0383166114405760405162461bcd60e51b815260206004820152603a60248201527f45746e795374616b696e673a20526577617264206164647265737320666f722060448201527f6f70657261746f7220776173206e6f742070726f7669646564210000000000006064820152608401610ade565b336001600160a01b038416036114cd5760405162461bcd60e51b815260206004820152604660248201527f45746e795374616b696e673a2052657761726420616464726573732073686f7560448201527f6c6420626520646966666572656e74207468616e20746865206e6f646520616460648201526564726573732160d01b608482015260a401610ade565b3360009081526015602052604090205460ff16156114fd5760405162461bcd60e51b8152600401610ade90618f1e565b6001600160401b0384166000908152600582016020526040812054600b80549192918390811061152f5761152f618d20565b600091825260208220600c909102019150600982015460ff1660048111156115595761155961864b565b146115cc5760405162461bcd60e51b815260206004820152603c60248201527f45746e795374616b696e673a204f6e6c792070656e64696e67207374616b696e60448201527f6720636f6e7472616374732063616e20626520617070726f76656421000000006064820152608401610ade565b6009810154600190600685019060009060ff1660048111156115f0576115f061864b565b60048111156116015761160161864b565b815260208101919091526040016000908120805490919061162c9084906001600160401b0316618f91565b82546101009290920a6001600160401b0381810219909316918316021790915560098301805460ff1916600190811790915542600785015560008181526006870160205260408120805492945092909161168891859116618fb0565b82546001600160401b039182166101009390930a92830291909202199091161790555060028301546001600160a01b031615611726576003810180546001600160a01b0319166001600160a01b0387161790556004830180547fffff00ffffffffffffffffffffffffff0000000000000000ffffffffffffffff81166001600160401b03909116600160401b0260ff60e81b191617600160e81b1790555b6004830154600160401b81046001600160401b039081169116148015611763575060008080526006840160205260409020546001600160401b0316155b1561177e5760048301805460ff60e81b1916600160e81b1790555b60408051838152602081018990527f492b38fe904dd9e188eb84bf5c076c5ba8391de320e4cda50c11fbc4faa5107f910160405180910390a15060019695505050505050565b6001546000906001600160a01b031633146117de57600080fd5b600a5482106117ff5760405162461bcd60e51b8152600401610ade90618e3a565b6000600a838154811061181457611814618d20565b9060005260206000209060070201905060005b60048201546001600160401b03600160801b90910481169082161015611a12576001600160401b0381166000908152600583016020526040812054600b8054909190811061187757611877618d20565b60009182526020909120600c9091020190506003600982015460ff1660048111156118a4576118a461864b565b1480156118b45750428160080154105b15611a09576009810154600190600685019060009060ff1660048111156118dd576118dd61864b565b60048111156118ee576118ee61864b565b81526020810191909152604001600090812080549091906119199084906001600160401b0316618f91565b82546101009290920a6001600160401b0381810219909316918316021790915560098301805460ff1916600490811790915560009081526006860160205260408120805460019450909261196f91859116618fb0565b82546101009290920a6001600160401b03818102199093169183160217909155600583015483546001600160a01b031660009081526014602052604081208054929093169350906119c1908490618fcf565b9091555050600581015460028201546001600160a01b0316600090815260126020526040812080546001600160401b0390931692909190611a03908490618fcf565b90915550505b50600101611827565b50600360009081526006820160205260409020546001600160401b0316158015611a555750600160009081526006820160205260409020546001600160401b0316155b8015611a78575060008080526006820160205260409020546001600160401b0316155b8015611aab57506004810154611aa0906001600160401b03600160401b820481169116618f91565b6001600160401b0316155b15611acb576004818101805460ff60e81b1916600160e81b835b02179055505b50600192915050565b6000546201000090046001600160a01b03163314611b045760405162461bcd60e51b8152600401610ade90618fe2565b6001600160a01b03166000908152600260205260409020805460ff19166001179055565b6001546001600160a01b03163314611b3f57600080fd5b3360009081526002602052604090205460ff16611b6e5760405162461bcd60e51b8152600401610ade90618c82565b6019805467ffffffffffffffff19166001600160401b0392909216919091179055565b600080600080600080600080600a8981548110611bb057611bb0618d20565b90600052602060002090600702019050888160040160109054906101000a90046001600160401b0316826006016000806004811115611bf157611bf161864b565b6004811115611c0257611c0261864b565b81526020808201929092526040908101600090812054600182526006969096019092528082205460028352818320546003845282842054600485529290932054949e939d506001600160401b039586169c5085169a5090841698508316965091169350915050565b6001546000906001600160a01b03163314611c8457600080fd5b600a548210611ca55760405162461bcd60e51b8152600401610ade90618d9d565b6000600a8381548110611cba57611cba618d20565b6000918252602090912060079091020180549091506001600160a01b03163314611cf65760405162461bcd60e51b8152600401610ade90619017565b6000600482810154600160e81b900460ff1690811115611d1857611d1861864b565b1480611d4357506001600482810154600160e81b900460ff1690811115611d4157611d4161864b565b145b611dcb5760405162461bcd60e51b815260206004820152604d60248201527f45746e795374616b696e673a20457874656e646564207374616b6520706f6f6c60448201527f2063616e6e6f742062652063616e63656c65642e20497420686173206469666660648201526c6572656e74207374617475732160981b608482015260a401610ade565b60048101805460ff60e81b1916600360e81b1790556040805184815290517fed2eddad45e3518d4213edaae6c788ba893dc504b673a7f55821b62adb85b4349181900360200190a160005b60048201546001600160401b03600160801b909104811690821610156121a0576001600160401b0381166000908152600583016020526040812054600b805491929183908110611e6857611e68618d20565b6000918252602082206009600c9092020190810154909250600191600687019160ff166004811115611e9c57611e9c61864b565b6004811115611ead57611ead61864b565b8152602081019190915260400160009081208054909190611ed89084906001600160401b0316618f91565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555060006004811115611f0f57611f0f61864b565b600982015460ff166004811115611f2857611f2861864b565b036120035760098101805460ff1916600417905542600682018190556008820155600a810154604080518481526020810192909252600080516020619517833981519152910160405180910390a160058101546004850180546001600160401b0392831692600891611fa3918591600160401b900416618f91565b82546101009290920a6001600160401b03818102199093169183160217909155600583015460028401546001600160a01b03166000908152601260205260408120805492909316935090611ff8908490618fcf565b9091555061210d9050565b6001600982015460ff16600481111561201e5761201e61864b565b0361210d5760098101805460ff191660031790554260068201556005810154600782015460405163d83102cd60e01b815261ffff600160801b90930492909216600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af41580156120a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c89190618d84565b6008820155600a8101546040805184815260208101929092527fb503cf14e3d55841fd2c9a549abd732f6898fde969da012639aa917173e3a006910160405180910390a15b6009810154600190600686019060009060ff1660048111156121315761213161864b565b60048111156121425761214261864b565b815260208101919091526040016000908120805490919061216d9084906001600160401b0316618fb0565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555050508080600101915050611e16565b5060048101546000906121c5906001600160401b03600160401b820481169116618f91565b6001600160401b03161115611acb5760048101546121f5906001600160401b03600160401b820481169116618f91565b33600090815260146020526040812080546001600160401b039390931692909190612221908490618fcf565b90915550506004018054600160401b81046001600160401b031667ffffffffffffffff19909116179055506001919050565b6001546001600160a01b0316331461226a57600080fd5b3360009081526002602052604090205460ff166122995760405162461bcd60e51b8152600401610ade90618c82565b6018805460ff191660ff92909216919091179055565b6001546000906001600160a01b031633146122c957600080fd5b50336000908152600d602052604090205490565b6000546201000090046001600160a01b0316331461230d5760405162461bcd60e51b8152600401610ade90618fe2565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600060128161233f82600a61914f565b6001600160a01b03851660009081526014602052604090205490915061236690829061915b565b949350505050565b6001546001600160a01b0316331461238557600080fd5b3360009081526002602052604090205460ff166123b45760405162461bcd60e51b8152600401610ade90618c82565b601880546001600160401b03909216600160901b0267ffffffffffffffff60901b19909216919091179055565b6001546060906001600160a01b031633146123fb57600080fd5b336000908152600e60209081526040918290208054835181840281018401909452808452909183018282801561245057602002820191906000526020600020905b81548152602001906001019080831161243c575b5050505050905090565b6001546000906001600160a01b0316331461247457600080fd5b600a5482106124955760405162461bcd60e51b8152600401610ade90618e3a565b6000600a83815481106124aa576124aa618d20565b906000526020600020906007020190506000805b60048301546001600160401b03600160801b909104811690821610156125f0576001600160401b0381166000908152600584016020526040812054600b8054909190811061250e5761250e618d20565b600091825260208220600c9091020191506001600983015460ff16600481111561253a5761253a61864b565b036125d3576005820154600783015460405163d83102cd60e01b8152600160801b90920461ffff16600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af41580156125a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125cc9190618d84565b90506125da565b5060088101545b808410156125e6578093505b50506001016124be565b509392505050565b6000806000806000806000806000600160009054906101000a90046001600160a01b03166001600160a01b0316336001600160a01b03161461263957600080fd5b6009548a1061265a5760405162461bcd60e51b8152600401610ade90618cd4565b600060098b8154811061266f5761266f618d20565b6000918252602091829020604080516101008101825260069390930290910180546001600160a01b0390811684526001820154811694840194909452600281015490931690820152600382015460608201526004808301546001600160401b0381166080840152600160401b810461ffff1660a084015291929160c0840191600160501b90910460ff16908111156127095761270961864b565b600481111561271a5761271a61864b565b815260200160058201548152505090508a816000015182602001518360400151846060015185608001518660a001518760c0015160008261ffff169250995099509950995099509950995099509950509193959799909294969850565b6001546000906001600160a01b0316331461279157600080fd5b60095482106127b25760405162461bcd60e51b8152600401610ade90618cd4565b6000600983815481106127c7576127c7618d20565b6000918252602090912060069091020190506003600482810154600160501b900460ff16908111156127fb576127fb61864b565b146128185760405162461bcd60e51b8152600401610ade90618d36565b6000600b82600501548154811061283157612831618d20565b90600052602060002090600c02019050428160080154106128a35760405162461bcd60e51b815260206004820152602660248201527f45746e795374616b696e673a205374616b65206973206e6f742065787069726560448201526564207965742160d01b6064820152608401610ade565b6004828101805460ff60501b1916600160521b17905560098201805460ff19169091179055600581015481546001600160a01b0316600090815260146020526040812080546001600160401b0390931692909190612902908490618fcf565b90915550506002810180546001600160a01b039081166000908152600f60209081526040808320805460ff191690556005860154945490931682526012905290812080546001600160401b0390931692909190612960908490618fcf565b9091555050600201546001600160a01b03166000908152601560205260409020805460ff1916905550600192915050565b6001546000906001600160a01b031633146129ab57600080fd5b503360009081526012602052604090205490565b6001546001600160a01b031633146129d657600080fd5b3360009081526002602052604090205460ff161515600114612a7e5760405162461bcd60e51b815260206004820152606160248201526000805160206194f783398151915260448201527f6573732063616e207465726d696e61746520616e20457874656e64656420537460648201527f616b6520436f6e747261637420616e64206170706c792070656e616c746965736084820152602160f81b60a482015260c401610ade565b600b548110612a9f5760405162461bcd60e51b8152600401610ade90618e3a565b6000600b8281548110612ab457612ab4618d20565b60009182526020909120600c9091020190506001600b82015460ff166001811115612ae157612ae161864b565b14612b545760405162461bcd60e51b815260206004820152603760248201527f45746e795374616b696e673a20416e20457874656e646564205374616b65204360448201527f6f6e7472616374206964206973206578706563746564210000000000000000006064820152608401610ade565b6003600982015460ff166004811115612b6f57612b6f61864b565b14612b8c5760405162461bcd60e51b8152600401610ade90619172565b42816008015410612baf5760405162461bcd60e51b8152600401610ade906191c5565b80546005820154612bd2916001600160a01b0316906001600160401b03166179cd565b60028101546005820154612bf8916001600160a01b0316906001600160401b0316617aaa565b6000600a82600a015481548110612c1157612c11618d20565b906000526020600020906007020190508160050160009054906101000a90046001600160401b03168160040160088282829054906101000a90046001600160401b0316612c5e9190618f91565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550612c8e82826004617b65565b612c9781617c9d565b600a82015460408051858152602081019290925260008051602061951783398151915291015b60405180910390a1505050565b6001546000906001600160a01b03163314612ce457600080fd5b5033600090815260126020526040902054151590565b6001546000906001600160a01b03163314612d1457600080fd5b336000908152600d60205260409020548210612d425760405162461bcd60e51b8152600401610ade90618e3a565b336000908152600d6020526040902080548390811061101a5761101a618d20565b6001546000906001600160a01b03163314612d7d57600080fd5b6001600160a01b03821660009081526015602052604090205460ff16612df05760405162461bcd60e51b815260206004820152602260248201527f45746e795374616b696e673a204e6f6465206973206e6f742063616e63656c65604482015261642160f01b6064820152608401610ade565b6001600160a01b0382166000908152600e6020526040902054612e7b5760405162461bcd60e51b815260206004820152603960248201527f45746e795374616b696e673a204e6f6465206973206e6f7420686176696e672060448201527f616e792062617365207374616b657320726571756573747321000000000000006064820152608401610ade565b6001600160a01b0382166000908152600e6020526040812054612ea090600190618fcf565b6001600160a01b0384166000908152600e602052604081208054929350909183908110612ecf57612ecf618d20565b90600052602060002001549050600060098281548110612ef157612ef1618d20565b6000918252602090912060069091020190506001600482810154600160501b900460ff1690811115612f2557612f2561864b565b1480612f4f575060048082810154600160501b900460ff1690811115612f4d57612f4d61864b565b145b612fb75760405162461bcd60e51b815260206004820152603360248201527f45746e795374616b696e673a2043616e6e6f74206578656375746520636c65616044820152726e7570206f6e2074686973207374617475732160681b6064820152608401610ade565b505050506001600160a01b03166000908152601560205260409020805460ff19169055600190565b6000546201000090046001600160a01b0316331461300f5760405162461bcd60e51b8152600401610ade90618fe2565b60008054604051620100009091046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805462010000600160b01b0319169055565b6001546000906001600160a01b0316331461307a57600080fd5b600a54841061309b5760405162461bcd60e51b8152600401610ade90618d9d565b6001600160a01b0382166130c15760405162461bcd60e51b8152600401610ade90619222565b336001600160a01b03831603613141576040805162461bcd60e51b81526020600482015260248101919091527f45746e795374616b696e673a205265776172642061646472657373206d75737460448201527f20626520646966666572656e74207468616e206e6f64652061646472657373216064820152608401610ade565b6019546001600160401b0390811690841610156131c65760405162461bcd60e51b815260206004820152603f60248201527f45746e795374616b696e673a2054686520616d6f756e74206973206c6f77657260448201527f207468616e206d696e20657874656e646564207374616b652076616c756521006064820152608401610ade565b3360009081526015602052604090205460ff16156131f65760405162461bcd60e51b8152600401610ade90618f1e565b6000600a858154811061320b5761320b618d20565b6000918252602082206007909102019150600482810154600160e81b900460ff169081111561323c5761323c61864b565b146132595760405162461bcd60e51b8152600401610ade90618d36565b60028101546001600160a01b031633036132d25760405162461bcd60e51b815260206004820152603460248201527f45746e795374616b696e673a20596f752063616e6e6f74206170706c7920746f6044820152732074686973205374616b6520526571756573742160601b6064820152608401610ade565b60048101546001600160401b03808216916132f691600160401b9091041686618fb0565b6001600160401b031611156133705760405162461bcd60e51b8152602060048201526046602482015260008051602061953783398151915260448201527f74686520617661696c61626c6520616d6f756e7420696e2063757272656e74206064820152657374616b652160d01b608482015260a401610ade565b60048101546001600160801b9091046001600160401b0316118015906133a257506004810154600160d81b900460ff16155b806133b857506004810154600160d81b900460ff165b6134205760405162461bcd60e51b815260206004820152603360248201527f45746e795374616b696e673a2054686973207374616b652063616e20616363656044820152727074206f6e6c79203120636f6e74726163742160681b6064820152608401610ade565b336000908152601260205260409020546134a25760405162461bcd60e51b815260206004820152603860248201527f45746e795374616b696e673a204e65656420746f2068617665206174206c656160448201527f7374206f6e652062617365207374616b652073657475702100000000000000006064820152608401610ade565b601654336000908152601260205260409020546134c9906001600160401b03871690619272565b11156135215760405162461bcd60e51b8152602060048201526033602482015260008051602061953783398151915260448201527274686520746f74616c206f662037353030302160681b6064820152608401610ade565b6004810154600160d81b900460ff1615156000036135b05760048101546001600160401b038581169116146135b05760405162461bcd60e51b815260206004820152602f60248201527f45746e795374616b696e673a2054686973207374616b696e6720706f6f6c206360448201526e616e6e6f742062652073706c69742160881b6064820152608401610ade565b838160040160088282829054906101000a90046001600160401b03166135d69190618fb0565b82546001600160401b039182166101009390930a9283029282021916919091179091556004830154600160401b810482169116149050801561362357506004810154600160e01b900460ff165b1561363e5760048101805460ff60e81b1916600160e81b1790555b8054600182015460048301546000928392613682926001600160a01b039283169233921690600160c01b810461ffff16908b908d90600160d01b900460ff16617d09565b6003820180546001600160a01b0319166001600160a01b03891617905560048501549193509150600160e01b900460ff16156136ce5760098201805460ff191660011790554260078301555b6009820154600190600685019060009060ff1660048111156136f2576136f261864b565b60048111156137035761370361864b565b815260208101919091526040016000908120805490919061372e9084906001600160401b0316618fb0565b82546101009290920a6001600160401b03818102199093169183160217909155600485018054600160801b90819004831660009081526005880160205260409020859055815460019450919260109261378b928692910416618fb0565b82546101009290920a6001600160401b0381810219909316918316021790915533600081815260116020908152604080832080546001818101835591855283852001889055938352601082528083208054948501815583528183209093018c9055600587015460028801546001600160a01b03168352601290915291812080549290931693509061381d908490619272565b909155505060028201546001600160a01b03166000818152601260209081526040918290205482518b8152918201527f859208af8cfda136750efa35f96dbecdddfae3cf3fe2242c8722870edee6ddde910160405180910390a25060019695505050505050565b6001546000906001600160a01b0316331461389e57600080fd5b50336000908152600e602052604090205490565b6001546000906001600160a01b031633146138cc57600080fd5b600a5482106138ed5760405162461bcd60e51b8152600401610ade90618d9d565b6000600a838154811061390257613902618d20565b6000918252602090912060079091020180549091506001600160a01b0316331461397e5760405162461bcd60e51b815260206004820152602760248201527f45746e795374616b696e673a204f6e6c79207374616b65722063616e2063616c6044820152666c20746869732160c81b6064820152608401610ade565b6000600482810154600160e81b900460ff16908111156139a0576139a061864b565b14806139cb57506003600482810154600160e81b900460ff16908111156139c9576139c961864b565b145b6139e75760405162461bcd60e51b8152600401610ade90618d36565b6003600482810154600160e81b900460ff1690811115613a0957613a0961864b565b03613a80576004810154600160801b90046001600160401b0316613a805760405162461bcd60e51b815260206004820152602860248201527f45746e795374616b696e673a205374616b6520686173206e6f20746f6b656e73604482015267206c6f636b65642160c01b6064820152608401610ade565b60048101546001600160401b03600160401b82048116911611613af95760405162461bcd60e51b815260206004820152602b60248201527f45746e795374616b696e673a20546865726520617265206e6f20746f6b656e7360448201526a20746f20756e6c6f636b2160a81b6064820152608401610ade565b6004810154613b1a906001600160401b03600160401b820481169116618f91565b33600090815260146020526040812080546001600160401b039390931692909190613b46908490618fcf565b9091555050600481018054600160401b81046001600160401b031667ffffffffffffffff199091168117909155158015613b9f57506000600482810154600160e81b900460ff1690811115613b9d57613b9d61864b565b145b15613bbe5760048101805460ff60e81b1916600360e81b179055613bd4565b60048101805460ff60e81b1916600160e81b1790555b33600090815260146020908152604091829020548251868152918201527f1ecc5ef7074a468a8b94f3c0c74cd118529219ec2801efefe9351818a4a46bb2910160405180910390a150600192915050565b6001546001600160a01b03163314613c3c57600080fd5b3360009081526002602052604090205460ff16613c6b5760405162461bcd60e51b8152600401610ade90618c82565b6018805460ff9092166101000261ff0019909216919091179055565b6001546000906001600160a01b03163314613ca157600080fd5b6009548210613cc25760405162461bcd60e51b8152600401610ade90618cd4565b600060098381548110613cd757613cd7618d20565b6000918252602090912060069091020180549091506001600160a01b03163314613d135760405162461bcd60e51b8152600401610ade90619017565b6000600482810154600160501b900460ff1690811115613d3557613d3561864b565b1480613d6057506001600482810154600160501b900460ff1690811115613d5e57613d5e61864b565b145b613d7c5760405162461bcd60e51b8152600401610ade90618d36565b60048101805460ff60501b1916600360501b1790556005810154600b8054600092908110613dac57613dac618d20565b600091825260208220600c909102019150600982015460ff166004811115613dd657613dd661864b565b03613e995760098101805460ff1916600417905542600682018190556008820155600581015481546001600160a01b0316600090815260146020526040812080546001600160401b0390931692909190613e31908490618fcf565b909155505060028101546001600160a01b03166000908152600f6020908152604091829020805460ff19169055600584015491519182527f2b7d80106cf63960f0324ea49c2f7f872886bdfb6cab927918027dd6d0f314f691015b60405180910390a16145fa565b60098101805460ff1990811660031790915542600683015560028201546001600160a01b03166000908152601560209081526040918290208054909316600117909255600584015490519081527fff4d02402ef330920f2f7bfb4a8a15a187a10f1d4f607e9f3d55e6611ef4afe3910160405180910390a160005b60028201546001600160a01b03166000908152601160205260409020548110156144335760028201546001600160a01b03166000908152601160205260408120805483908110613f6657613f66618d20565b906000526020600020015490506000600b8281548110613f8857613f88618d20565b90600052602060002090600c020190506000600a82600a015481548110613fb157613fb1618d20565b6000918252602082206007909102019150600983015460ff166004811115613fdb57613fdb61864b565b1480613fff57506001600983015460ff166004811115613ffd57613ffd61864b565b145b15614089576009820154600190600683019060009060ff1660048111156140285761402861864b565b60048111156140395761403961864b565b81526020810191909152604001600090812080549091906140649084906001600160401b0316618f91565b92506101000a8154816001600160401b0302191690836001600160401b031602179055505b6000600983015460ff1660048111156140a4576140a461864b565b036142155760098201805460ff1916600417905542600683018190556008830155600a820154604080518581526020810192909252600080516020619517833981519152910160405180910390a1600582015460028301546001600160a01b0316600090815260126020526040812080546001600160401b039093169290919061412f908490618fcf565b909155505060058201546004820180546001600160401b0392831692600891614161918591600160401b900416618f91565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555060018160060160008460090160009054906101000a900460ff1660048111156141b0576141b061864b565b60048111156141c1576141c161864b565b81526020810191909152604001600090812080549091906141ec9084906001600160401b0316618fb0565b92506101000a8154816001600160401b0302191690836001600160401b031602179055506143aa565b6001600983015460ff1660048111156142305761423061864b565b036143aa5760098201805460ff191660031790554260068301556005820154600783015460405163d83102cd60e01b815261ffff600160801b90930492909216600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af41580156142b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142da9190618d84565b60088301556009820154600190600683019060009060ff1660048111156143035761430361864b565b60048111156143145761431461864b565b815260208101919091526040016000908120805490919061433f9084906001600160401b0316618fb0565b92506101000a8154816001600160401b0302191690836001600160401b031602179055507fb503cf14e3d55841fd2c9a549abd732f6898fde969da012639aa917173e3a0068383600a01546040516143a1929190918252602082015260400190565b60405180910390a15b8160080154856008015410156143c557600880830154908601555b6001600482810154600160e81b900460ff16908111156143e7576143e761864b565b14801561440d5750600160009081526006820160205260409020546001600160401b0316155b156144285760048101805460ff60e81b1916600360e81b1790555b505050600101613f14565b5080600801546000036145fa5760195460058201546001600160401b03600160801b9092048216911610156145675760098101805460ff1916600417905542600682018190556008820155600581015481546001600160a01b0316600090815260146020526040812080546001600160401b03909316929091906144b8908490618fcf565b90915550506002810180546001600160a01b039081166000908152600f60209081526040808320805460ff1990811690915585548516845260158352818420805490911690556005860154945490931682526012905290812080546001600160401b039093169290919061452d908490618fcf565b909155505060058201546040519081527f2b7d80106cf63960f0324ea49c2f7f872886bdfb6cab927918027dd6d0f314f690602001613e8c565b6005810154600782015460405163d83102cd60e01b8152600160801b90920461ffff16600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af41580156145d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145f49190618d84565b60088201555b5060019392505050565b60008060008060008060008060008060006009805490508d106146395760405162461bcd60e51b8152600401610ade90618cd4565b600060098e8154811061464e5761464e618d20565b906000526020600020906006020190508c6001600160401b03166000146146875760405162461bcd60e51b8152600401610ade90618ded565b6000816005015490506000600b82815481106146a5576146a5618d20565b90600052602060002090600c020190508f8f838560000160009054906101000a90046001600160a01b03168460020160009054906101000a90046001600160a01b03168560030160009054906101000a90046001600160a01b031686600401548760050160009054906101000a90046001600160401b03168860050160109054906101000a900461ffff168960090160009054906101000a900460ff168a600801548261ffff1692509d509d509d509d509d509d509d509d509d509d509d505050509295989b509295989b9093969950565b6001546000906001600160a01b0316331461479157600080fd5b503360009081526010602052604090205490565b6001546000906001600160a01b031633146147bf57600080fd5b506019546001600160401b031690565b6001546000906001600160a01b031633146147e957600080fd5b600954821061480a5760405162461bcd60e51b8152600401610ade90618cd4565b60006009838154811061481f5761481f618d20565b6000918252602090912060069091020160028101549091506001600160a01b031633146148b45760405162461bcd60e51b815260206004820152603960248201527f45746e795374616b696e673a204f6e6c79206e6f6465206f70657261746f722060448201527f63616e206465636c696e652074686973207265717565737421000000000000006064820152608401610ade565b6000600482810154600160501b900460ff16908111156148d6576148d661864b565b146148f35760405162461bcd60e51b8152600401610ade90618d36565b60048101805460ff60501b1916600160511b1790556005810154600b805460009290811061492357614923618d20565b600091825260208083206009600c90930201918201805460ff19166002179055600582015482546001600160a01b0316845260149091526040832080549294506001600160401b0390911692909161497c908490618fcf565b9091555050336000908152601260209081526040808320839055600f9091529020805460ff191690555060019392505050565b6001546001600160a01b031633146149c657600080fd5b3360009081526002602052604090205460ff166149f55760405162461bcd60e51b8152600401610ade90618c82565b601880546001600160401b03909216600160501b0267ffffffffffffffff60501b19909216919091179055565b6000546201000090046001600160a01b03163314614a525760405162461bcd60e51b8152600401610ade90618fe2565b6001600160a01b03166000908152600260205260409020805460ff19169055565b600080600080600080600080600080600a805490508c10614aa65760405162461bcd60e51b8152600401610ade90618d9d565b6000600a8d81548110614abb57614abb618d20565b906000526020600020906007020190508060040160109054906101000a90046001600160401b03166001600160401b03168c6001600160401b031610614b135760405162461bcd60e51b8152600401610ade90618ded565b6001600160401b038c166000908152600582016020526040812054600b805491929183908110614b4557614b45618d20565b600091825260208220919550600c020190506001600982015460ff166004811115614b7257614b7261864b565b03614c0b576005810154600782015460405163d83102cd60e01b8152600160801b90920461ffff16600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af4158015614be0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c049190618d84565b9350614c13565b806008015493505b8e8e838560000160009054906101000a90046001600160a01b03168460020160009054906101000a90046001600160a01b031685600401548660050160009054906101000a90046001600160401b03168760050160109054906101000a900461ffff168860090160009054906101000a900460ff168c8261ffff1692509c509c509c509c509c509c509c509c509c509c505050509295989b9194979a5092959850565b6001546000906001600160a01b03163314614cd057600080fd5b600a548310614cf15760405162461bcd60e51b8152600401610ade90618d9d565b6000600a8481548110614d0657614d06618d20565b906000526020600020906007020190508060040160109054906101000a90046001600160401b03166001600160401b0316836001600160401b031610614d5e5760405162461bcd60e51b8152600401610ade90618ded565b6001600160401b0383166000908152600582016020526040812054600b805491929183908110614d9057614d90618d20565b600091825260208220600c909102019150600982015460ff166004811115614dba57614dba61864b565b14614e2d5760405162461bcd60e51b815260206004820152603c60248201527f45746e795374616b696e673a204f6e6c792070656e64696e67207374616b696e60448201527f6720636f6e7472616374732063616e206265206465636c696e656421000000006064820152608401610ade565b6009810154600190600685019060009060ff166004811115614e5157614e5161864b565b6004811115614e6257614e6261864b565b8152602081019190915260400160009081208054909190614e8d9084906001600160401b0316618f91565b82546101009290920a6001600160401b0381810219909316918316021790915560098301805460ff19166002908117909155600090815260068601602052604081208054600194509092614ee391859116618fb0565b82546101009290920a6001600160401b038181021990931691831602179091556005830154600486018054918316935091600891614f2a918591600160401b900416618f91565b82546101009290920a6001600160401b03818102199093169183160217909155600583015460028401546001600160a01b03166000908152601260205260408120805492909316935090614f7f908490618fcf565b909155505060028301546001600160a01b031615614fec5760048301805460ff60e81b1916600160e91b179055600581015481546001600160a01b0316600090815260146020526040812080546001600160401b0390931692909190614fe6908490618fcf565b90915550505b60408051838152602081018890527fa6d35207a3d1012ac29345fe2aeabf0b1dc6285e13a1dbca53d5738524323a54910160405180910390a150600195945050505050565b6001546000906001600160a01b0316331461504b57600080fd5b5060165490565b6001546000906001600160a01b0316331461506c57600080fd5b3360009081526002602052604090205460ff1615156001146150a05760405162461bcd60e51b8152600401610ade90619285565b600b5483106150c15760405162461bcd60e51b8152600401610ade90618e3a565b6000600b84815481106150d6576150d6618d20565b60009182526020909120600c9091020190506003600982015460ff1660048111156151035761510361864b565b146151205760405162461bcd60e51b8152600401610ade90619172565b428160080154106151435760405162461bcd60e51b8152600401610ade906191c5565b6001600b82015460ff16600181111561515e5761515e61864b565b036151715761516c846129bf565b6145fa565b61517d84846001616825565b505060019392505050565b6001546000906001600160a01b031633146151a257600080fd5b3360009081526002602052604090205460ff1615156001146151d65760405162461bcd60e51b8152600401610ade90618e7e565b6000600a83815481106151eb576151eb618d20565b600091825260208220600460079092020190810180549193509060ff60e81b1916600160e81b83611ac5565b6001546001600160a01b0316331461522e57600080fd5b3360009081526002602052604090205460ff1661525d5760405162461bcd60e51b8152600401610ade90618c82565b600780546001600160a01b0319166001600160a01b0392909216919091179055565b6001546000906001600160a01b0316331461529957600080fd5b6007546001600160a01b03166152c15760405162461bcd60e51b8152600401610ade906192f6565b6001600160a01b03841661532d5760405162461bcd60e51b815260206004820152602d60248201527f45746e795374616b696e673a206e6f646520616464726573732069732074686560448201526c207a65726f206164647265737360981b6064820152608401610ade565b6001600160a01b03841633036153b55760405162461bcd60e51b815260206004820152604160248201527f45746e795374616b696e673a20546865206e6f64652061646472657373206d7560448201527f737420626520646966666572656e74207468616e2063757272656e74206f6e656064820152602160f81b608482015260a401610ade565b601854610100900460ff1661ffff831610156154265760405162461bcd60e51b815260206004820152602a60248201527f45746e795374616b696e673a20546865207374616b696e6720706572696f6420604482015269697320746f206c6f772160b01b6064820152608401610ade565b6018546001600160401b03600160501b90910481169084161080159061546257506019546001600160401b03600160401b909104811690841611155b6154d45760405162461bcd60e51b815260206004820152603f60248201527f45746e795374616b696e673a20616d6f756e74206d757374206265206265747760448201527f65656e206d696e696d756d20616e64206d6178696d756d2076616c75657321006064820152608401610ade565b6001600160a01b0384166000908152601260205260409020541561550a5760405162461bcd60e51b8152600401610ade90619386565b6001600160a01b0384166000908152600f602052604090205460ff16156155435760405162461bcd60e51b8152600401610ade90619386565b600061554e85617f86565b9050801561556e5760405162461bcd60e51b8152600401610ade906193db565b600061557933617f86565b336000908152601460205260409020549091506001600160401b038616906155a19083618fcf565b10156155bf5760405162461bcd60e51b8152600401610ade9061941d565b336000818152600c60209081526040808320600980548254600180820185559387528587200155546001600160a01b038c168552600e84528285208054928301815585529383902001839055518281529195507fd7490e816438b23e3486aef50b4dfd914be81021d62b1db81226227291f6c85b910160405180910390a260008061565133896000898b8a6064617d09565b600b8201805492945090925060009160ff1916600183021790555060408051610100810182523381526000602082018190526001600160a01b038b16928201929092524260608201526001600160401b038916608082015261ffff881660a082015260099160c082019081526020908101849052825460018082018555600094855293829020835160069092020180546001600160a01b03199081166001600160a01b03938416178255928401519481018054841695831695909517909455604083015160028501805490931691161790556060810151600383015560808101516004808401805460a08501516001600160401b0390941669ffffffffffffffffffff1990911617600160401b61ffff909416939093029290921780835560c0840151939493929160ff60501b1990911690600160501b90849081111561579a5761579a61864b565b021790555060e0919091015160059091015533600090815260146020526040812080546001600160401b038a1692906157d4908490619272565b9091555050506001600160a01b0387166000908152600f60205260409020805460ff191660011790555050509392505050565b6001546000906001600160a01b0316331461582157600080fd5b6007546001600160a01b03166158495760405162461bcd60e51b8152600401610ade906192f6565b8360ff166064146158c2576001600160a01b0386166158c25760405162461bcd60e51b815260206004820152602f60248201527f45746e795374616b696e673a207265776172642061646472657373206973207460448201526e6865207a65726f206164647265737360881b6064820152608401610ade565b6019546001600160401b03908116908816101561592d5760405162461bcd60e51b815260206004820152602360248201527f45746e795374616b696e673a2054686520616d6f756e7420697320746f30206c6044820152626f772160e81b6064820152608401610ade565b601854610100900460ff1661ffff861610156159965760405162461bcd60e51b815260206004820152602260248201527f45746e795374616b696e673a2054686520706572696f6420697320746f206c6f604482015261772160f01b6064820152608401610ade565b60658460ff1610615a0f5760405162461bcd60e51b815260206004820152603860248201527f45746e795374616b696e673a20546865206f70657261746f722072657761726460448201527f2070657263656e7461676520697320746f6f20686967682100000000000000006064820152608401610ade565b336001600160a01b03871603615a9f5760405162461bcd60e51b815260206004820152604960248201527f45746e795374616b696e673a205468652063757272656e74206164647265737360448201527f2073686f756c6420626520646966666572656e74207468616e2072657761726460648201526820616464726573732160b81b608482015260a401610ade565b6001600160a01b03881615615d39576001600160a01b03881660009081526015602052604090205460ff1615615b3d5760405162461bcd60e51b815260206004820152603e60248201527f45746e795374616b696e673a205468652062617365207374616b6520636f6e7460448201527f72616374206f6e20746865206e6f6465207761732063616e63656c65642100006064820152608401610ade565b6001600160a01b038816600090815260126020526040902054615bc85760405162461bcd60e51b815260206004820152603860248201527f45746e795374616b696e673a20546865206e6f646520646f65736e277420686160448201527f766520616e792062617365207374616b652073657475702100000000000000006064820152608401610ade565b6001600160a01b0388163303615c395760405162461bcd60e51b815260206004820152603060248201527f45746e795374616b696e673a20546865206e6f64652061646472657373206d7560448201526f737420626520646966666572656e742160801b6064820152608401610ade565b876001600160a01b0316866001600160a01b031603615c6a5760405162461bcd60e51b8152600401610ade90619468565b6016546001600160a01b038916600090815260126020526040902054615c9a906001600160401b038a1690619272565b1115615d0c5760405162461bcd60e51b8152602060048201526047602482015260008051602061953783398151915260448201527f746865206d6178696d756d20616c6c6f77656420746f6b656e73206f6e20746860648201526665206e6f64652160c81b608482015260a401610ade565b6000615d1789617f86565b90508015615d375760405162461bcd60e51b8152600401610ade906193db565b505b6000615d4433617f86565b336000908152601460205260409020549091506001600160401b03891690615d6c9083618fcf565b1015615d8a5760405162461bcd60e51b8152600401610ade9061941d565b6000600a6001816001815401808255809150500390600052602060002090600702019050338160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550878160010160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550898160020160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550428160030181905550888160040160006101000a8154816001600160401b0302191690836001600160401b0316021790555060008160040160086101000a8154816001600160401b0302191690836001600160401b0316021790555060008160040160106101000a8154816001600160401b0302191690836001600160401b03160217905550868160040160186101000a81548161ffff021916908361ffff1602179055508581600401601a6101000a81548160ff021916908360ff1602179055508481600401601b6101000a81548160ff0219169083151502179055508381600401601c6101000a81548160ff021916908315150217905550600081600401601d6101000a81548160ff02191690836004811115615f4a57615f4a61864b565b0217905550600a54615f5e90600190618fcf565b60405181815290935033907ffb7b213a27fb2f9ada24dbc107b98a959d208d5a39fb37f481b80ff7cc4ec4b49060200160405180910390a2336000908152600d60209081526040822080546001810182559083529120018390556001600160a01b038a16156161555780546000908190615fe6906001600160a01b03168d8c8c8f8a8e617d09565b60098201549193509150600190600685019060009060ff16600481111561600f5761600f61864b565b60048111156160205761602061864b565b815260208101919091526040016000908120805490919061604b9084906001600160401b0316618fb0565b82546101009290920a6001600160401b03818102199093169183160217909155600485018054600160801b9081900483166000908152600588016020526040902085905581546001945091926010926160a8928692910416618fb0565b82546101009290920a6001600160401b0381810219909316918316021790915560048501805467ffffffffffffffff60401b1916600160401b928f169283021790556001600160a01b038e166000818152601060209081526040808320805460018181018355918552838520018c905584845260118352818420805491820181558452828420018790559282526012905290812080549293509161614d908490619272565b909155505050505b33600090815260146020526040812080546001600160401b038c16929061617d908490619272565b90915550505050979650505050505050565b6001546060906001600160a01b031633146161a957600080fd5b3360009081526010602090815260409182902080548351818402810184019094528084529091830182828015612450576020028201919060005260206000209081548152602001906001019080831161243c575050505050905090565b6001546000906001600160a01b0316331461622057600080fd5b50601854600160501b90046001600160401b031690565b6001546000906001600160a01b0316331461625157600080fd5b5060185460ff1690565b6001546001600160a01b0316331461627257600080fd5b3360009081526002602052604090205460ff166162a15760405162461bcd60e51b8152600401610ade90618c82565b601980546001600160401b03909216600160401b0267ffffffffffffffff60401b19909216919091179055565b6001600160a01b0381166000908152600e60209081526040808320600f83528184205460128452828520546015855283862054835485518188028101880190965280865260609796879687969560ff90811695941692909186919083018282801561635857602002820191906000526020600020905b815481526020019060010190808311616344575b5050505050935093509350935093509193509193565b6001546000906001600160a01b0316331461638857600080fd5b50600a5490565b60015460009081908190819081906001600160a01b031633146163b157600080fd5b600b5486106163d25760405162461bcd60e51b8152600401610ade90618e3a565b6000600b87815481106163e7576163e7618d20565b600091825260208220919450600c020190506001600982015460ff1660048111156164145761641461864b565b036164ad576005810154600782015460405163d83102cd60e01b8152600160801b90920461ffff16600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af4158015616482573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906164a69190618d84565b92506164b5565b806008015492505b600481015460078201546008830154600690930154919990985091965092945091925050565b6001546000906001600160a01b031633146164f557600080fd5b336000908152600e602052604090205482106165235760405162461bcd60e51b8152600401610ade90618e3a565b336000908152600e6020526040902080548390811061101a5761101a618d20565b6001546000906001600160a01b0316331461655e57600080fd5b3360009081526002602052604090205460ff1615156001146165f25760405162461bcd60e51b815260206004820152605360248201526000805160206194f783398151915260448201527f6573732063616e207465726d696e61746520612042617365205374616b6520616064820152726e64206170706c792070656e616c746965732160681b608482015260a401610ade565b600b5482106166135760405162461bcd60e51b8152600401610ade90618ec9565b6000600b838154811061662857616628618d20565b90600052602060002090600c020190506000600982600a01548154811061665157616651618d20565b9060005260206000209060060201905064012117d1578260080154106166df5760405162461bcd60e51b815260206004820152603860248201527f45746e795374616b696e673a2054686520636f6e74726163742077617320616c60448201527f72656164792070726f6c6f6e67656420666f72657665722100000000000000006064820152608401610ade565b6166e881618013565b600982018054600360ff199182161790915542600684015564012117d15760088401556002830180546001600160a01b03908116600090815260156020908152604080832080548716600190811790915594549093168252600f90522080549092161790556167568261802f565b60028201546001600160a01b03166000908152601260209081526040918290205491519182527f1fe3c8d9b22341d7ceb24f6a7806432c03c741b526bec20edf6a49bc22b20bc2910160405180910390a15060019392505050565b6001546000906001600160a01b031633146167cb57600080fd5b50600b5490565b6001546000906001600160a01b031633146167ec57600080fd5b506007546001600160a01b031690565b6001546000906001600160a01b0316331461681657600080fd5b50601854610100900460ff1690565b6001546000906001600160a01b0316331461683f57600080fd5b3360009081526002602052604090205460ff1615156001146168735760405162461bcd60e51b8152600401610ade90619285565b600b5484106168945760405162461bcd60e51b8152600401610ade90618e3a565b6000600b85815481106168a9576168a9618d20565b600091825260208220600c909102019150600b82015460ff1660018111156168d3576168d361864b565b1461693b5760405162461bcd60e51b815260206004820152603260248201527f45746e795374616b696e673a20412042617365205374616b6520436f6e74726160448201527163742069642069732065787065637465642160701b6064820152608401610ade565b6003600982015460ff1660048111156169565761695661864b565b146169735760405162461bcd60e51b8152600401610ade90619172565b82156169825761698281618184565b428160080154106169a55760405162461bcd60e51b8152600401610ade906191c5565b6000600982600a0154815481106169be576169be618d20565b906000526020600020906006020190506169d78261822d565b84616ac75760028201546005830154616a02916001600160a01b0316906001600160401b0316617aaa565b600982018054600460ff1991821617909155426006840181905560088401556002830180546001600160a01b03908116600090815260156020908152604080832080548716905593549092168152600f909152208054909116905581546004820154616a80916001600160a01b0316906001600160401b03166179cd565b616a8981618427565b6040518681527f2b7d80106cf63960f0324ea49c2f7f872886bdfb6cab927918027dd6d0f314f69060200160405180910390a1600192505050610f5f565b60006006830181905560028301546001600160a01b03168152601560205260409020805460ff191690556004810180546001919060ff60501b1916600160501b8302179055506009820180546001919060ff1916828002179055506005820154600783015460405163d83102cd60e01b8152600160801b90920461ffff16600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af4158015616b8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190616baf9190618d84565b60088301556040518681527f36e5b23050bb3a750f3648961be392c7f7ddad7be9d63439307a6381168b3a049060200160405180910390a150600195945050505050565b6001546000906001600160a01b03163314616c0d57600080fd5b50336000908152600c602052604090205490565b6001546000906001600160a01b03163314616c3b57600080fd5b6009548310616c5c5760405162461bcd60e51b8152600401610ade90618cd4565b6001600160a01b038216616c825760405162461bcd60e51b8152600401610ade90619222565b336001600160a01b03831603616caa5760405162461bcd60e51b8152600401610ade90619468565b600060098481548110616cbf57616cbf618d20565b6000918252602090912060069091020160028101549091506001600160a01b03163314616d545760405162461bcd60e51b815260206004820152603760248201527f45746e795374616b696e673a206f6e6c79206e6f6465206f70657261746f722060448201527f63616e20617070726f76652062617365207374616b65210000000000000000006064820152608401610ade565b6000600482810154600160501b900460ff1690811115616d7657616d7661864b565b14616dda5760405162461bcd60e51b815260206004820152602e60248201527f45746e795374616b696e673a207374616b65206d757374206265206e6577207460448201526d6f20626520617070726f7665642160901b6064820152608401610ade565b60048101805460ff60501b1916600160501b1790556001810180546001600160a01b0319166001600160a01b0385161790556005810154600b8054600092908110616e2757616e27618d20565b600091825260208083206009600c90930201918201805460ff191660011790554260078301556003820180546001600160a01b0389166001600160a01b0319909116179055600582015433845260129091526040832080549294506001600160401b03909116929091616e9b908490619272565b909155505033600090815260126020908152604091829020548251888152918201527f1dbef83c751dbba35b43f07c7ba982ca00b3627cd0d733b6c55870a6ea4bce56910160405180910390a1506001949350505050565b6001600160a01b0381166000908152600e6020908152604091829020805483518184028101840190945280845260609392830182828015616f5357602002820191906000526020600020905b815481526020019060010190808311616f3f575b50505050509050919050565b6001546001600160a01b03163314616f7657600080fd5b3360009081526002602052604090205460ff16616fa55760405162461bcd60e51b8152600401610ade90618c82565b601755565b6001546000906001600160a01b03163314616fc457600080fd5b336000908152601060205260409020548210616ff25760405162461bcd60e51b8152600401610ade90618e3a565b33600090815260106020526040902080548390811061101a5761101a618d20565b6001546000906001600160a01b0316331461702d57600080fd5b50601954600160401b90046001600160401b031690565b600080600080600080600080600080600080600080600a8f8154811061706c5761706c618d20565b906000526020600020906007020190508e8160000160009054906101000a90046001600160a01b03168260010160009054906101000a90046001600160a01b03168360020160009054906101000a90046001600160a01b031684600301548560040160009054906101000a90046001600160401b03168660040160089054906101000a90046001600160401b03168760040160189054906101000a900461ffff1688600401601a9054906101000a900460ff1689600401601b9054906101000a900460ff168a600401601c9054906101000a900460ff168b600401601d9054906101000a900460ff168c60040160109054906101000a90046001600160401b03168561ffff1695509d509d509d509d509d509d509d509d509d509d509d509d509d505091939597999b9d90929496989a9c50565b6000546201000090046001600160a01b031633146171d05760405162461bcd60e51b8152600401610ade90618fe2565b6001600160a01b0381166172355760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610ade565b600080546040516001600160a01b03808516936201000090930416917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b6001546000906001600160a01b031633146172b857600080fd5b3360009081526002602052604090205460ff166172e75760405162461bcd60e51b8152600401610ade90618c82565b600b5484106173085760405162461bcd60e51b8152600401610ade90618e3a565b6000600b858154811061731d5761731d618d20565b600091825260209091206003600c90920201908101549091506001600160a01b0385811691161461739e5760405162461bcd60e51b815260206004820152602560248201527f45746e795374616b696e673a2072657761726420616464726573732070726f76604482015264696465642160d81b6064820152608401610ade565b60030180546001600160a01b0384166001600160a01b03199091161790555060019392505050565b6001546000906001600160a01b031633146173e057600080fd5b60006173eb33617f86565b336000908152601460205260409020549091506174089082618fcf565b91505090565b6001546000906001600160a01b0316331461742857600080fd5b6000600985015460ff1660048111156174435761744361864b565b148061746757506001600985015460ff1660048111156174655761746561864b565b145b6174ea5760405162461bcd60e51b815260206004820152604860248201527f45746e795374616b696e673a204f6e6c792070656e64696e67206f722061707060448201527f726f766564207374616b696e6720636f6e7472616374732063616e2062652063606482015267616e63656c65642160c01b608482015260a401610ade565b83546001600160a01b031633148061750e575060028401546001600160a01b031633145b8061752d57503360009081526002602052604090205460ff1615156001145b6175c55760405162461bcd60e51b815260206004820152605760248201527f45746e795374616b696e673a204f6e6c79207374616b65686f6c6465722c206e60448201527f6f6465206f70657261746f72206f7220636f6d70616e7961646472657373206360648201527f616e2063616e63656c2074686520636f6e747261637421000000000000000000608482015260a401610ade565b6009840154600190600687019060009060ff1660048111156175e9576175e961864b565b60048111156175fa576175fa61864b565b81526020810191909152604001600090812080549091906176259084906001600160401b0316618f91565b92506101000a8154816001600160401b0302191690836001600160401b031602179055506000600481111561765c5761765c61864b565b600985015460ff1660048111156176755761767561864b565b036177c05760098401805460ff1916600417905542600685018190556008850155600a840154604080518581526020810192909252600080516020619517833981519152910160405180910390a160058401546004860180546001600160401b03928316926008916176f0918591600160401b900416618f91565b82546101009290920a6001600160401b03818102199093169183160217909155600586015460028701546001600160a01b03166000908152601260205260408120805492909316935090617745908490618fcf565b909155505060028501546001600160a01b0316156177bb576004850180546001600160801b0360ff60e81b011916600160ea1b179055600584015484546001600160a01b0316600090815260146020526040812080546001600160401b03909316929091906177b5908490618fcf565b90915550505b61793d565b6001600985015460ff1660048111156177db576177db61864b565b0361793d573360009081526002602052604090205460ff16151560010361780c57617807858585618440565b6178f6565b60098401805460ff191660031790554260068501556005840154600785015460405163d83102cd60e01b815261ffff600160801b90930492909216600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af415801561788d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906178b19190618d84565b6008850155600a8401546040805185815260208101929092527fb503cf14e3d55841fd2c9a549abd732f6898fde969da012639aa917173e3a006910160405180910390a15b83546001600160a01b031633148061792257503360009081526002602052604090205460ff1615156001145b1561793d57600b8401805461ff001916610100841515021790555b6009840154600190600687019060009060ff1660048111156179615761796161864b565b60048111156179725761797261864b565b815260208101919091526040016000908120805490919061799d9084906001600160401b0316618fb0565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555060019050949350505050565b6001600160a01b0382166000908152601460205260409020546001600160401b0382161115617a705760405162461bcd60e51b815260206004820152604360248201527f496e73756666696369656e74207374616b6520686f6c646572206c6f636b656460448201527f20746f6b656e7320696e207374616b696e6720666f722073756274726163746960648201526237b71760e91b608482015260a401610ade565b6001600160a01b038216600090815260146020526040812080546001600160401b0384169290617aa1908490618fcf565b90915550505050565b6001600160a01b0382166000908152601260205260409020546001600160401b0382161115617b345760405162461bcd60e51b815260206004820152603060248201527f496e73756666696369656e74206e6f6465207374616b656420746f6b656e732060448201526f3337b91039bab13a3930b1ba34b7b71760811b6064820152608401610ade565b6001600160a01b038216600090815260126020526040812080546001600160401b0384169290617aa1908490618fcf565b6009830154600190600684019060009060ff166004811115617b8957617b8961864b565b6004811115617b9a57617b9a61864b565b8152602081019190915260400160009081208054909190617bc59084906001600160401b0316618f91565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550808360090160006101000a81548160ff02191690836004811115617c0f57617c0f61864b565b02179055506009830154600190600684019060009060ff166004811115617c3857617c3861864b565b6004811115617c4957617c4961864b565b8152602081019190915260400160009081208054909190617c749084906001600160401b0316618fb0565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550505050565b6001600482810154600160e81b900460ff1690811115617cbf57617cbf61864b565b148015617ce357506004810154600160401b81046001600160401b03908116911614155b15617d06576004810180546000919060ff60e81b1916600160e81b835b02179055505b50565b600b8054600180820183556000928352600c82027f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9810180546001600160a01b039c8d166001600160a01b03199182161782557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbb830180549c8e169c82169c909c17909b557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dba820180549a909c16998b1699909917909a557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbc8a018054909916909855427f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbd8a01557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbe890180547f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbf8b018490557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dc18b018490557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dc08b01939093557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dc38a01949094557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dc28901805460ff199081169091557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dc49099018054909916909717909755600160401b60ff9091160261ffff93909316600160801b0271ffff0000000000000000ffffffffffffffff199096166001600160401b0392909216919091179490941767ffffffffffffffff60401b1916179092559091565b6000601281617f9682600a61914f565b6007546040516370a0823160e01b81526001600160a01b0387811660048301529293508392909116906370a0823190602401602060405180830381865afa158015617fe5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906180099190618d84565b61236691906194d4565b6004810180546003919060ff60501b1916600160501b83617d00565b60005b60028201546001600160a01b03166000908152601160205260409020548110156181805760028201546001600160a01b0316600090815260116020526040812080548390811061808457618084618d20565b906000526020600020015490506000600b82815481106180a6576180a6618d20565b90600052602060002090600c020190506000600a82600a0154815481106180cf576180cf618d20565b6000918252602090912060079091020190506003600983015460ff1660048111156180fc576180fc61864b565b036181225761810c818385618440565b600b8201805461ff001916610100179055618175565b6000600983015460ff16600481111561813d5761813d61864b565b148061816157506001600983015460ff16600481111561815f5761815f61864b565b145b1561817557618173818385600161740e565b505b505050600101618032565b5050565b60005b60028201546001600160a01b03166000908152601160205260409020548110156181805760028201546001600160a01b031660009081526011602052604081208054839081106181d9576181d9618d20565b906000526020600020015490506000600b82815481106181fb576181fb618d20565b90600052602060002090600c0201600801549050808460080154101561822357600884018190555b5050600101618187565b60005b60028201546001600160a01b03166000908152601160205260409020548110156181805760028201546001600160a01b0316600090815260116020526040812080548390811061828257618282618d20565b906000526020600020015490506000600b82815481106182a4576182a4618d20565b90600052602060002090600c020190506000600a82600a0154815481106182cd576182cd618d20565b6000918252602090912060079091020190506003600983015460ff1660048111156182fa576182fa61864b565b14801561830a5750428260080154105b15618413576183198282618615565b8154600583015461833c916001600160a01b0316906001600160401b03166179cd565b60028201546005830154618362916001600160a01b0316906001600160401b0316617aaa565b60058201546004820180546001600160401b039283169260089161838f918591600160401b900416618f91565b82546001600160401b039182166101009390930a92830291909202199091161790555060028101546001600160a01b0316156184135760048101805460ff60e81b1916600160ea1b179055600a8201546040519081527fa002debc9839c20f8a9424b3c4bad3295abbb3676c3acf6ea94d869f6b4f54c09060200160405180910390a15b61841c81617c9d565b505050600101618230565b6004818101805460ff60501b1916600160501b83617d00565b60098201805460ff191660049081179091554260068401819055600880850191909155600584015491850180546001600160401b0393841693919291618490918591600160401b90910416618f91565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550600160048111156184c7576184c761864b565b600484810154600160e81b900460ff16908111156184e7576184e761864b565b036184fc5760048301805460ff60e81b191690555b600582015460028301546001600160a01b0316600090815260126020526040812080546001600160401b0390931692909190618539908490618fcf565b9091555050600a820154604080518381526020810192909252600080516020619517833981519152910160405180910390a160028301546001600160a01b031615618610576004830180546001600160801b0360ff60e81b011916600160ea1b179055600582015482546001600160a01b0316600090815260146020526040812080546001600160401b03909316929091906185d6908490618fcf565b9091555050600a8201546040519081527fa002debc9839c20f8a9424b3c4bad3295abbb3676c3acf6ea94d869f6b4f54c090602001612cbd565b505050565b61862182826004617b65565b504260068201819055600890910155565b60006020828403121561864457600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60058110617d0657617d0661864b565b61867a81618661565b9052565b6002811061867a5761867a61864b565b8b81526001600160a01b038b811660208301528a8116604083015289811660608301528816608082015260a081018790526001600160401b0386811660c083015285811660e0830152841661010082015261016081016186f2610120830185618671565b61870061014083018461867e565b9c9b505050505050505050505050565b80356001600160401b0381168114610bd757600080fd5b80358015158114610bd757600080fd5b60008060006060848603121561874c57600080fd5b8335925061875c60208501618710565b915061876a60408501618727565b90509250925092565b6000806000806080858703121561878957600080fd5b5050823594602084013594506040840135936060013592509050565b80356001600160a01b0381168114610bd757600080fd5b600080604083850312156187cf57600080fd5b6187d8836187a5565b91506187e660208401618710565b90509250929050565b60008060006060848603121561880457600080fd5b8335925061881460208501618710565b915061876a604085016187a5565b60006020828403121561883457600080fd5b610f5f826187a5565b60006020828403121561884f57600080fd5b610f5f82618710565b803560ff81168114610bd757600080fd5b60006020828403121561887b57600080fd5b610f5f82618858565b600081518084526020840193506020830160005b828110156188b6578151865260209586019590910190600101618898565b5093949350505050565b602081526000610f5f6020830184618884565b8981526001600160a01b038981166020830152888116604083015287166060820152608081018690526001600160401b0385811660a0830152841660c0820152610120810161892184618661565b8360e083015261893561010083018461867e565b9a9950505050505050505050565b6000806040838503121561895657600080fd5b823591506187e660208401618710565b8b81526001600160401b038b81166020830152604082018b90526001600160a01b038a811660608401528981166080840152881660a083015260c0820187905285811660e0830152841661010082015261016081016189c9610120830185618671565b826101408301529c9b505050505050505050505050565b8a81526001600160401b038a81166020830152604082018a90526001600160a01b0389811660608401528816608083015260a0820187905285811660c0830152841660e08201526101408101618a3584618661565b610100820193909352610120015298975050505050505050565b60008060408385031215618a6257600080fd5b823591506187e660208401618727565b803561ffff81168114610bd757600080fd5b600080600060608486031215618a9957600080fd5b618aa2846187a5565b9250618ab060208501618710565b915061876a60408501618a72565b600080600080600080600060e0888a031215618ad957600080fd5b618ae2886187a5565b9650618af060208901618710565b9550618afe604089016187a5565b9450618b0c60608901618a72565b9350618b1a60808901618858565b9250618b2860a08901618727565b9150618b3660c08901618727565b905092959891949750929550565b608081526000618b576080830187618884565b94151560208301525060408101929092521515606090910152919050565b600080600060608486031215618b8a57600080fd5b8335925061875c60208501618727565b60008060408385031215618bad57600080fd5b823591506187e6602084016187a5565b8d81526001600160a01b038d811660208301528c811660408301528b166060820152608081018a90526001600160401b0389811660a0830152881660c08201526101a081016001600160401b03881660e083015260ff8716610100830152851515610120830152841515610140830152618c3b610160830185618671565b6001600160401b0383166101808301529e9d5050505050505050505050505050565b600080600060608486031215618c7257600080fd5b83359250618814602085016187a5565b60208082526032908201527f436f6d70616e7957616c6c65743a2063616c6c6572206973206e6f7420612077604082015271616c6c65742066726f6d20636f6d70616e7960701b606082015260800190565b6020808252602c908201527f45746e795374616b696e673a20496e76616c69642042617365205374616b652060408201526b49442070726f76696465642160a01b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b6020808252602e908201527f45746e795374616b696e673a205374616b6520697320686176696e672064696660408201526d666572656e74207374617475732160901b606082015260800190565b600060208284031215618d9657600080fd5b5051919050565b60208082526030908201527f45746e795374616b696e673a20496e76616c696420457874656e64656420537460408201526f616b652049442070726f76696465642160801b606082015260800190565b6020808252602d908201527f45746e795374616b696e673a20496e76616c6964205374616b6520436f6e747260408201526c6163742070726f76696465642160981b606082015260800190565b60208082526024908201527f45746e795374616b696e673a20496e76616c696420496e6465782070726f76696040820152636465642160e01b606082015260800190565b6020808252603c908201526000805160206194f783398151915260408201527f6573732063616e20706572666f726d207468697320616374696f6e2100000000606082015260800190565b60208082526035908201527f45746e795374616b696e673a20496e76616c69642042617365205374616b6520604082015274436f6e74726163742049442070726f76696465642160581b606082015260800190565b6020808252603f908201527f45746e795374616b696e673a205468652062617365207374616b6520636f6e7460408201527f72616374206f6e2074686973206e6f6465207761732063616e63656c65642100606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6001600160401b03828116828216039081111561128a5761128a618f7b565b6001600160401b03818116838216019081111561128a5761128a618f7b565b8181038181111561128a5761128a618f7b565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f45746e795374616b696e673a204f6e6c79207374616b65722063616e2063616e60408201527063656c207468697320726571756573742160781b606082015260800190565b6001815b60018411156190a35780850481111561908757619087618f7b565b600184161561909557908102905b60019390931c92800261906c565b935093915050565b6000826190ba5750600161128a565b816190c75750600061128a565b81600181146190dd57600281146190e757619103565b600191505061128a565b60ff8411156190f8576190f8618f7b565b50506001821b61128a565b5060208310610133831016604e8410600b8410161715619126575081810a61128a565b6191336000198484619068565b806000190482111561914757619147618f7b565b029392505050565b6000610f5f83836190ab565b808202811582820484141761128a5761128a618f7b565b60208082526033908201527f45746e795374616b696e673a204f6e6c7920612063616e63656c656420636f6e60408201527274726163742063616e20626520656e6465642160681b606082015260800190565b6020808252603d908201527f45746e795374616b696e673a2054686520636f6e74726163742063616e20626560408201527f207465726d696e6174656420616674657220697420657870697265732e000000606082015260800190565b60208082526030908201527f45746e795374616b696e673a205265776172642061646472657373206973207460408201526f6865207a65726f20616464726573732160801b606082015260800190565b8082018082111561128a5761128a618f7b565b6020808252605c908201526000805160206194f783398151915260408201527f6573732063616e207465726d696e61746520612042617365205374616b65204360608201527f6f6e747261637420616e64206170706c792070656e616c746965732100000000608082015260a00190565b60208082526064908201527f45746e795374616b696e673a20536f6d657468696e672077656e742077726f6e60408201527f672e205468652045746865726e69747920436c6f756420536d617274436f6e7460608201527f726163742061646472657373206973206e6f7420636f72726563746c792073656080820152637475702160e01b60a082015260c00190565b60208082526035908201527f45746e795374616b696e673a204e6f646520616c72656164792068617320616e604082015274206578697374696e672062617365207374616b652160581b606082015260800190565b60208082526022908201527f45746e795374616b696e673a204e6f6465206861732045544e5920746f6b656e604082015261732160f01b606082015260800190565b6020808252603e9082015260008051602061953783398151915260408201527f62616c616e636520617661696c61626c6520666f72207374616b696e67210000606082015260800190565b60208082526046908201527f45746e795374616b696e673a20546865206e6f6465206164647265737320736860408201527f6f756c6420626520646966666572656e74207468616e2072657761726420616460608201526564726573732160d01b608082015260a00190565b6000826194f157634e487b7160e01b600052601260045260246000fd5b50049056fe45746e795374616b696e673a204f6e6c79206120636f6d70616e792061646472ee821fc4af1ea42a6c6174adb5fd292ad9e326c120629b92006d036545c3c66b45746e795374616b696e673a2054686520616d6f756e74206578636565647320a2646970667358221220d86e6e6f8fa2602a52df3e5b9fd1ef7f79783917d841e44134aa8a5a6c94a9ae64736f6c634300081a0033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106104695760003560e01c80638caafbff1161024c578063c573a9b611610146578063db797e81116100c3578063ea55e31911610087578063ea55e31914610a42578063f2fde38b14610a6e578063f3b5397414610a81578063f8a25c5614610a94578063faa8aab114610a9c57600080fd5b8063db797e81146109ec578063de7c883014610a01578063e0768b1814610a14578063e8454f0714610a27578063e99edf4114610a3a57600080fd5b8063cd7f0bcc1161010a578063cd7f0bcc146109ae578063cf3c3287146109b6578063d53ce9a9146109be578063d598ed98146109d1578063da67129a146109d957600080fd5b8063c573a9b61461093d578063c6aa90ef14610945578063c756023914610980578063c8f00e7514610993578063c91951c7146109a657600080fd5b8063ab205d08116101d4578063b3036c6411610198578063b3036c64146108dd578063b6b7b3cf146108e5578063b6c4ab71146108ed578063b6ecc1cc14610907578063bafb35811461091a57600080fd5b8063ab205d081461087e578063ac870fe814610891578063af68faae146108a4578063b06ba626146108b7578063b2bdfa7b146108ca57600080fd5b806390cadc5a1161021b57806390cadc5a1461081457806391a8c1c514610827578063946e203f14610850578063a4f8277314610863578063a6f958c81461086b57600080fd5b80638caafbff146107cf5780638cd03f77146107d75780638d2adf32146107ea5780638da5cb5b146107fd57600080fd5b8063458dcf6a1161036857806367e40097116102e55780638014522d116102a95780638014522d1461076457806380605c931461077757806383082bb21461078a57806383c8eed91461079d57806388b4ec28146107c757600080fd5b806367e400971461071b5780636b2963551461072e578063715018a614610741578063749490b8146107495780637c5045e81461075c57600080fd5b80635d0d71661161032c5780635d0d7166146106bd5780635eba1aa3146106e557806362647959146106f8578063676465401461070057806367a53be31461071357600080fd5b8063458dcf6a14610644578063488b8e8b146106575780634d263b611461066a578063512532891461067f5780635c60da1b1461069257600080fd5b806328d9228c116103f657806337daa815116103ba57806337daa815146105ab578063380ae6be1461060357806339ad083d146106165780633b7973ed14610629578063438787d01461063157600080fd5b806328d9228c1461054c57806329e0a52b1461055f57806329e7d373146105725780632e14edaa146105855780633348dccd1461059857600080fd5b806311e776fe1161043d57806311e776fe146104db5780631492794d146104f0578063194dc6c8146105115780631c4bc72914610519578063275fdda51461053957600080fd5b8062226faa1461046e578063033751a2146104965780630b0e33d0146104c05780630ef7ef77146104c8575b600080fd5b61048161047c366004618632565b610aaf565b60405190151581526020015b60405180910390f35b6104a96104a4366004618632565b610bdc565b60405161048d9b9a9998979695949392919061868e565b610481610e37565b6104816104d6366004618737565b610e63565b6104ee6104e9366004618632565b610f66565b005b6105036104fe366004618632565b610fb1565b60405190815260200161048d565b61050361102c565b61052161104d565b6040516001600160401b03909116815260200161048d565b610481610547366004618773565b61107d565b61048161055a3660046187bc565b611214565b61048161056d3660046187ef565b611290565b610481610580366004618632565b6117c4565b6104ee610593366004618822565b611ad4565b6104ee6105a636600461883d565b611b28565b6105be6105b9366004618632565b611b91565b604080519788526001600160401b03968716602089015294861694870194909452918416606086015283166080850152821660a08401521660c082015260e00161048d565b610481610611366004618632565b611c6a565b6104ee610624366004618869565b612253565b6105036122af565b6104ee61063f366004618822565b6122dd565b610503610652366004618822565b61232f565b6104ee61066536600461883d565b61236e565b6106726123e1565b60405161048d91906188c0565b61050361068d366004618632565b61245a565b6003546106a5906001600160a01b031681565b6040516001600160a01b03909116815260200161048d565b6106d06106cb366004618632565b6125f8565b60405161048d999897969594939291906188d3565b6104816106f3366004618632565b612777565b610503612991565b6104ee61070e366004618632565b6129bf565b610481612cca565b610503610729366004618632565b612cfa565b61048161073c366004618822565b612d63565b6104ee612fdf565b6104816107573660046187ef565b613060565b610503613884565b610481610772366004618632565b6138b2565b6104ee610785366004618869565b613c25565b610481610798366004618632565b613c87565b6107b06107ab366004618943565b614604565b60405161048d9b9a99989796959493929190618966565b610503614777565b6105216147a5565b6104816107e5366004618632565b6147cf565b6104ee6107f836600461883d565b6149af565b6000546201000090046001600160a01b03166106a5565b6104ee610822366004618822565b614a22565b61083a610835366004618943565b614a73565b60405161048d9a999897969594939291906189e0565b61048161085e366004618943565b614cb6565b610503615031565b610481610879366004618a4f565b615052565b61048161088c366004618632565b615188565b6104ee61089f366004618822565b615217565b6105036108b2366004618a84565b61527f565b6105036108c5366004618abe565b615807565b6005546106a5906001600160a01b031681565b61067261618f565b610521616206565b6108f5616237565b60405160ff909116815260200161048d565b6104ee61091536600461883d565b61625b565b61092d610928366004618822565b6162ce565b60405161048d9493929190618b44565b61050361636e565b610958610953366004618632565b61638f565b604080519586526020860194909452928401919091526060830152608082015260a00161048d565b61050361098e366004618632565b6164db565b6104816109a1366004618632565b616544565b6105036167b1565b6106a56167d2565b6108f56167fc565b6104816109cc366004618b75565b616825565b610503616bf3565b6104816109e7366004618b9a565b616c21565b33600090815260146020526040902054610503565b610672610a0f366004618822565b616ef3565b6104ee610a22366004618632565b616f5f565b610503610a35366004618632565b616faa565b610521617013565b610a55610a50366004618632565b617044565b60405161048d9d9c9b9a99989796959493929190618bbd565b6104ee610a7c366004618822565b6171a0565b610481610a8f366004618c5d565b61729e565b6105036173c6565b6001546106a5906001600160a01b031681565b3360009081526002602052604081205460ff16610ae75760405162461bcd60e51b8152600401610ade90618c82565b60405180910390fd5b6009548210610b085760405162461bcd60e51b8152600401610ade90618cd4565b600060098381548110610b1d57610b1d618d20565b6000918252602090912060069091020190506001600482810154600160501b900460ff1690811115610b5157610b5161864b565b14610b6e5760405162461bcd60e51b8152600401610ade90618d36565b60048101805460ff60501b1916600360501b1790556005810154600b8054600092908110610b9e57610b9e618d20565b600091825260209091206009600c90920201908101805460ff1916600317905542600682015564012117d1576008909101555060019150505b919050565b6000806000806000806000806000806000600b805490508c10610c5a5760405162461bcd60e51b815260206004820152603060248201527f45746e795374616b696e673a20496e76616c6964205374616b6520636f6e747260448201526f6163742049442070726f76696465642160801b6064820152608401610ade565b6000600b8d81548110610c6f57610c6f618d20565b600091825260208220919d50600c020190506001600982015460ff166004811115610c9c57610c9c61864b565b03610d35576005810154600782015460405163d83102cd60e01b8152600160801b90920461ffff16600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af4158015610d0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2e9190618d84565b9b50610d3d565b80600801549b505b8b8160000160009054906101000a90046001600160a01b03168260020160009054906101000a90046001600160a01b03168360030160009054906101000a90046001600160a01b03168460010160009054906101000a90046001600160a01b031685600401548660050160009054906101000a90046001600160401b03168760050160089054906101000a90046001600160401b03168860050160109054906101000a900461ffff168960090160009054906101000a900460ff168a600b0160009054906101000a900460ff168261ffff1692509b509b509b509b509b509b509b509b509b509b509b505091939597999b90929496989a50565b6001546000906001600160a01b03163314610e5157600080fd5b506007546001600160a01b0316151590565b6001546000906001600160a01b03163314610e7d57600080fd5b600a548410610e9e5760405162461bcd60e51b8152600401610ade90618d9d565b6000600a8581548110610eb357610eb3618d20565b906000526020600020906007020190508060040160109054906101000a90046001600160401b03166001600160401b0316846001600160401b031610610f0b5760405162461bcd60e51b8152600401610ade90618ded565b6001600160401b0384166000908152600582016020526040812054600b805491929183908110610f3d57610f3d618d20565b90600052602060002090600c02019050610f598382848861740e565b93505050505b9392505050565b6001546001600160a01b03163314610f7d57600080fd5b3360009081526002602052604090205460ff16610fac5760405162461bcd60e51b8152600401610ade90618c82565b601655565b6001546000906001600160a01b03163314610fcb57600080fd5b336000908152600c60205260409020548210610ff95760405162461bcd60e51b8152600401610ade90618e3a565b336000908152600c6020526040902080548390811061101a5761101a618d20565b90600052602060002001549050919050565b6001546000906001600160a01b0316331461104657600080fd5b5060095490565b6001546000906001600160a01b0316331461106757600080fd5b506018546201000090046001600160401b031690565b6001546000906001600160a01b0316331461109757600080fd5b3360009081526002602052604090205460ff1615156001146110cb5760405162461bcd60e51b8152600401610ade90618e7e565b600b5485106110ec5760405162461bcd60e51b8152600401610ade90618ec9565b6000600b868154811061110157611101618d20565b90600052602060002090600c020190508260048111156111235761112361864b565b60098201805460ff191660018360048111156111415761114161864b565b02179055506008810185905560068101849055600a8101546009805460009290811061116f5761116f618d20565b906000526020600020906006020190508360048111156111915761119161864b565b81600401600a6101000a81548160ff021916908360048111156111b6576111b661864b565b02179055506003600482810154600160501b900460ff16908111156111dd576111dd61864b565b6002909201546001600160a01b03166000908152601560205260409020805460ff1916919092141790555060019050949350505050565b6001546000906001600160a01b0316331461122e57600080fd5b3360009081526002602052604090205460ff1615156001146112625760405162461bcd60e51b8152600401610ade90618e7e565b506001600160a01b03821660009081526014602052604090206001600160401b038216905560015b92915050565b6001546000906001600160a01b031633146112aa57600080fd5b600a5484106112cb5760405162461bcd60e51b8152600401610ade90618d9d565b6000600a85815481106112e0576112e0618d20565b906000526020600020906007020190508060040160109054906101000a90046001600160401b03166001600160401b0316846001600160401b0316106113385760405162461bcd60e51b8152600401610ade90618ded565b60028101546001600160a01b0316156114fd5760028101546001600160a01b031633146113c45760405162461bcd60e51b815260206004820152603460248201527f45746e795374616b696e673a204f6e6c79206f70657261746f722063616e20616044820152737070726f76652074686520636f6e74726163742160601b6064820152608401610ade565b6001600160a01b0383166114405760405162461bcd60e51b815260206004820152603a60248201527f45746e795374616b696e673a20526577617264206164647265737320666f722060448201527f6f70657261746f7220776173206e6f742070726f7669646564210000000000006064820152608401610ade565b336001600160a01b038416036114cd5760405162461bcd60e51b815260206004820152604660248201527f45746e795374616b696e673a2052657761726420616464726573732073686f7560448201527f6c6420626520646966666572656e74207468616e20746865206e6f646520616460648201526564726573732160d01b608482015260a401610ade565b3360009081526015602052604090205460ff16156114fd5760405162461bcd60e51b8152600401610ade90618f1e565b6001600160401b0384166000908152600582016020526040812054600b80549192918390811061152f5761152f618d20565b600091825260208220600c909102019150600982015460ff1660048111156115595761155961864b565b146115cc5760405162461bcd60e51b815260206004820152603c60248201527f45746e795374616b696e673a204f6e6c792070656e64696e67207374616b696e60448201527f6720636f6e7472616374732063616e20626520617070726f76656421000000006064820152608401610ade565b6009810154600190600685019060009060ff1660048111156115f0576115f061864b565b60048111156116015761160161864b565b815260208101919091526040016000908120805490919061162c9084906001600160401b0316618f91565b82546101009290920a6001600160401b0381810219909316918316021790915560098301805460ff1916600190811790915542600785015560008181526006870160205260408120805492945092909161168891859116618fb0565b82546001600160401b039182166101009390930a92830291909202199091161790555060028301546001600160a01b031615611726576003810180546001600160a01b0319166001600160a01b0387161790556004830180547fffff00ffffffffffffffffffffffffff0000000000000000ffffffffffffffff81166001600160401b03909116600160401b0260ff60e81b191617600160e81b1790555b6004830154600160401b81046001600160401b039081169116148015611763575060008080526006840160205260409020546001600160401b0316155b1561177e5760048301805460ff60e81b1916600160e81b1790555b60408051838152602081018990527f492b38fe904dd9e188eb84bf5c076c5ba8391de320e4cda50c11fbc4faa5107f910160405180910390a15060019695505050505050565b6001546000906001600160a01b031633146117de57600080fd5b600a5482106117ff5760405162461bcd60e51b8152600401610ade90618e3a565b6000600a838154811061181457611814618d20565b9060005260206000209060070201905060005b60048201546001600160401b03600160801b90910481169082161015611a12576001600160401b0381166000908152600583016020526040812054600b8054909190811061187757611877618d20565b60009182526020909120600c9091020190506003600982015460ff1660048111156118a4576118a461864b565b1480156118b45750428160080154105b15611a09576009810154600190600685019060009060ff1660048111156118dd576118dd61864b565b60048111156118ee576118ee61864b565b81526020810191909152604001600090812080549091906119199084906001600160401b0316618f91565b82546101009290920a6001600160401b0381810219909316918316021790915560098301805460ff1916600490811790915560009081526006860160205260408120805460019450909261196f91859116618fb0565b82546101009290920a6001600160401b03818102199093169183160217909155600583015483546001600160a01b031660009081526014602052604081208054929093169350906119c1908490618fcf565b9091555050600581015460028201546001600160a01b0316600090815260126020526040812080546001600160401b0390931692909190611a03908490618fcf565b90915550505b50600101611827565b50600360009081526006820160205260409020546001600160401b0316158015611a555750600160009081526006820160205260409020546001600160401b0316155b8015611a78575060008080526006820160205260409020546001600160401b0316155b8015611aab57506004810154611aa0906001600160401b03600160401b820481169116618f91565b6001600160401b0316155b15611acb576004818101805460ff60e81b1916600160e81b835b02179055505b50600192915050565b6000546201000090046001600160a01b03163314611b045760405162461bcd60e51b8152600401610ade90618fe2565b6001600160a01b03166000908152600260205260409020805460ff19166001179055565b6001546001600160a01b03163314611b3f57600080fd5b3360009081526002602052604090205460ff16611b6e5760405162461bcd60e51b8152600401610ade90618c82565b6019805467ffffffffffffffff19166001600160401b0392909216919091179055565b600080600080600080600080600a8981548110611bb057611bb0618d20565b90600052602060002090600702019050888160040160109054906101000a90046001600160401b0316826006016000806004811115611bf157611bf161864b565b6004811115611c0257611c0261864b565b81526020808201929092526040908101600090812054600182526006969096019092528082205460028352818320546003845282842054600485529290932054949e939d506001600160401b039586169c5085169a5090841698508316965091169350915050565b6001546000906001600160a01b03163314611c8457600080fd5b600a548210611ca55760405162461bcd60e51b8152600401610ade90618d9d565b6000600a8381548110611cba57611cba618d20565b6000918252602090912060079091020180549091506001600160a01b03163314611cf65760405162461bcd60e51b8152600401610ade90619017565b6000600482810154600160e81b900460ff1690811115611d1857611d1861864b565b1480611d4357506001600482810154600160e81b900460ff1690811115611d4157611d4161864b565b145b611dcb5760405162461bcd60e51b815260206004820152604d60248201527f45746e795374616b696e673a20457874656e646564207374616b6520706f6f6c60448201527f2063616e6e6f742062652063616e63656c65642e20497420686173206469666660648201526c6572656e74207374617475732160981b608482015260a401610ade565b60048101805460ff60e81b1916600360e81b1790556040805184815290517fed2eddad45e3518d4213edaae6c788ba893dc504b673a7f55821b62adb85b4349181900360200190a160005b60048201546001600160401b03600160801b909104811690821610156121a0576001600160401b0381166000908152600583016020526040812054600b805491929183908110611e6857611e68618d20565b6000918252602082206009600c9092020190810154909250600191600687019160ff166004811115611e9c57611e9c61864b565b6004811115611ead57611ead61864b565b8152602081019190915260400160009081208054909190611ed89084906001600160401b0316618f91565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555060006004811115611f0f57611f0f61864b565b600982015460ff166004811115611f2857611f2861864b565b036120035760098101805460ff1916600417905542600682018190556008820155600a810154604080518481526020810192909252600080516020619517833981519152910160405180910390a160058101546004850180546001600160401b0392831692600891611fa3918591600160401b900416618f91565b82546101009290920a6001600160401b03818102199093169183160217909155600583015460028401546001600160a01b03166000908152601260205260408120805492909316935090611ff8908490618fcf565b9091555061210d9050565b6001600982015460ff16600481111561201e5761201e61864b565b0361210d5760098101805460ff191660031790554260068201556005810154600782015460405163d83102cd60e01b815261ffff600160801b90930492909216600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af41580156120a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c89190618d84565b6008820155600a8101546040805184815260208101929092527fb503cf14e3d55841fd2c9a549abd732f6898fde969da012639aa917173e3a006910160405180910390a15b6009810154600190600686019060009060ff1660048111156121315761213161864b565b60048111156121425761214261864b565b815260208101919091526040016000908120805490919061216d9084906001600160401b0316618fb0565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555050508080600101915050611e16565b5060048101546000906121c5906001600160401b03600160401b820481169116618f91565b6001600160401b03161115611acb5760048101546121f5906001600160401b03600160401b820481169116618f91565b33600090815260146020526040812080546001600160401b039390931692909190612221908490618fcf565b90915550506004018054600160401b81046001600160401b031667ffffffffffffffff19909116179055506001919050565b6001546001600160a01b0316331461226a57600080fd5b3360009081526002602052604090205460ff166122995760405162461bcd60e51b8152600401610ade90618c82565b6018805460ff191660ff92909216919091179055565b6001546000906001600160a01b031633146122c957600080fd5b50336000908152600d602052604090205490565b6000546201000090046001600160a01b0316331461230d5760405162461bcd60e51b8152600401610ade90618fe2565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600060128161233f82600a61914f565b6001600160a01b03851660009081526014602052604090205490915061236690829061915b565b949350505050565b6001546001600160a01b0316331461238557600080fd5b3360009081526002602052604090205460ff166123b45760405162461bcd60e51b8152600401610ade90618c82565b601880546001600160401b03909216600160901b0267ffffffffffffffff60901b19909216919091179055565b6001546060906001600160a01b031633146123fb57600080fd5b336000908152600e60209081526040918290208054835181840281018401909452808452909183018282801561245057602002820191906000526020600020905b81548152602001906001019080831161243c575b5050505050905090565b6001546000906001600160a01b0316331461247457600080fd5b600a5482106124955760405162461bcd60e51b8152600401610ade90618e3a565b6000600a83815481106124aa576124aa618d20565b906000526020600020906007020190506000805b60048301546001600160401b03600160801b909104811690821610156125f0576001600160401b0381166000908152600584016020526040812054600b8054909190811061250e5761250e618d20565b600091825260208220600c9091020191506001600983015460ff16600481111561253a5761253a61864b565b036125d3576005820154600783015460405163d83102cd60e01b8152600160801b90920461ffff16600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af41580156125a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125cc9190618d84565b90506125da565b5060088101545b808410156125e6578093505b50506001016124be565b509392505050565b6000806000806000806000806000600160009054906101000a90046001600160a01b03166001600160a01b0316336001600160a01b03161461263957600080fd5b6009548a1061265a5760405162461bcd60e51b8152600401610ade90618cd4565b600060098b8154811061266f5761266f618d20565b6000918252602091829020604080516101008101825260069390930290910180546001600160a01b0390811684526001820154811694840194909452600281015490931690820152600382015460608201526004808301546001600160401b0381166080840152600160401b810461ffff1660a084015291929160c0840191600160501b90910460ff16908111156127095761270961864b565b600481111561271a5761271a61864b565b815260200160058201548152505090508a816000015182602001518360400151846060015185608001518660a001518760c0015160008261ffff169250995099509950995099509950995099509950509193959799909294969850565b6001546000906001600160a01b0316331461279157600080fd5b60095482106127b25760405162461bcd60e51b8152600401610ade90618cd4565b6000600983815481106127c7576127c7618d20565b6000918252602090912060069091020190506003600482810154600160501b900460ff16908111156127fb576127fb61864b565b146128185760405162461bcd60e51b8152600401610ade90618d36565b6000600b82600501548154811061283157612831618d20565b90600052602060002090600c02019050428160080154106128a35760405162461bcd60e51b815260206004820152602660248201527f45746e795374616b696e673a205374616b65206973206e6f742065787069726560448201526564207965742160d01b6064820152608401610ade565b6004828101805460ff60501b1916600160521b17905560098201805460ff19169091179055600581015481546001600160a01b0316600090815260146020526040812080546001600160401b0390931692909190612902908490618fcf565b90915550506002810180546001600160a01b039081166000908152600f60209081526040808320805460ff191690556005860154945490931682526012905290812080546001600160401b0390931692909190612960908490618fcf565b9091555050600201546001600160a01b03166000908152601560205260409020805460ff1916905550600192915050565b6001546000906001600160a01b031633146129ab57600080fd5b503360009081526012602052604090205490565b6001546001600160a01b031633146129d657600080fd5b3360009081526002602052604090205460ff161515600114612a7e5760405162461bcd60e51b815260206004820152606160248201526000805160206194f783398151915260448201527f6573732063616e207465726d696e61746520616e20457874656e64656420537460648201527f616b6520436f6e747261637420616e64206170706c792070656e616c746965736084820152602160f81b60a482015260c401610ade565b600b548110612a9f5760405162461bcd60e51b8152600401610ade90618e3a565b6000600b8281548110612ab457612ab4618d20565b60009182526020909120600c9091020190506001600b82015460ff166001811115612ae157612ae161864b565b14612b545760405162461bcd60e51b815260206004820152603760248201527f45746e795374616b696e673a20416e20457874656e646564205374616b65204360448201527f6f6e7472616374206964206973206578706563746564210000000000000000006064820152608401610ade565b6003600982015460ff166004811115612b6f57612b6f61864b565b14612b8c5760405162461bcd60e51b8152600401610ade90619172565b42816008015410612baf5760405162461bcd60e51b8152600401610ade906191c5565b80546005820154612bd2916001600160a01b0316906001600160401b03166179cd565b60028101546005820154612bf8916001600160a01b0316906001600160401b0316617aaa565b6000600a82600a015481548110612c1157612c11618d20565b906000526020600020906007020190508160050160009054906101000a90046001600160401b03168160040160088282829054906101000a90046001600160401b0316612c5e9190618f91565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550612c8e82826004617b65565b612c9781617c9d565b600a82015460408051858152602081019290925260008051602061951783398151915291015b60405180910390a1505050565b6001546000906001600160a01b03163314612ce457600080fd5b5033600090815260126020526040902054151590565b6001546000906001600160a01b03163314612d1457600080fd5b336000908152600d60205260409020548210612d425760405162461bcd60e51b8152600401610ade90618e3a565b336000908152600d6020526040902080548390811061101a5761101a618d20565b6001546000906001600160a01b03163314612d7d57600080fd5b6001600160a01b03821660009081526015602052604090205460ff16612df05760405162461bcd60e51b815260206004820152602260248201527f45746e795374616b696e673a204e6f6465206973206e6f742063616e63656c65604482015261642160f01b6064820152608401610ade565b6001600160a01b0382166000908152600e6020526040902054612e7b5760405162461bcd60e51b815260206004820152603960248201527f45746e795374616b696e673a204e6f6465206973206e6f7420686176696e672060448201527f616e792062617365207374616b657320726571756573747321000000000000006064820152608401610ade565b6001600160a01b0382166000908152600e6020526040812054612ea090600190618fcf565b6001600160a01b0384166000908152600e602052604081208054929350909183908110612ecf57612ecf618d20565b90600052602060002001549050600060098281548110612ef157612ef1618d20565b6000918252602090912060069091020190506001600482810154600160501b900460ff1690811115612f2557612f2561864b565b1480612f4f575060048082810154600160501b900460ff1690811115612f4d57612f4d61864b565b145b612fb75760405162461bcd60e51b815260206004820152603360248201527f45746e795374616b696e673a2043616e6e6f74206578656375746520636c65616044820152726e7570206f6e2074686973207374617475732160681b6064820152608401610ade565b505050506001600160a01b03166000908152601560205260409020805460ff19169055600190565b6000546201000090046001600160a01b0316331461300f5760405162461bcd60e51b8152600401610ade90618fe2565b60008054604051620100009091046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805462010000600160b01b0319169055565b6001546000906001600160a01b0316331461307a57600080fd5b600a54841061309b5760405162461bcd60e51b8152600401610ade90618d9d565b6001600160a01b0382166130c15760405162461bcd60e51b8152600401610ade90619222565b336001600160a01b03831603613141576040805162461bcd60e51b81526020600482015260248101919091527f45746e795374616b696e673a205265776172642061646472657373206d75737460448201527f20626520646966666572656e74207468616e206e6f64652061646472657373216064820152608401610ade565b6019546001600160401b0390811690841610156131c65760405162461bcd60e51b815260206004820152603f60248201527f45746e795374616b696e673a2054686520616d6f756e74206973206c6f77657260448201527f207468616e206d696e20657874656e646564207374616b652076616c756521006064820152608401610ade565b3360009081526015602052604090205460ff16156131f65760405162461bcd60e51b8152600401610ade90618f1e565b6000600a858154811061320b5761320b618d20565b6000918252602082206007909102019150600482810154600160e81b900460ff169081111561323c5761323c61864b565b146132595760405162461bcd60e51b8152600401610ade90618d36565b60028101546001600160a01b031633036132d25760405162461bcd60e51b815260206004820152603460248201527f45746e795374616b696e673a20596f752063616e6e6f74206170706c7920746f6044820152732074686973205374616b6520526571756573742160601b6064820152608401610ade565b60048101546001600160401b03808216916132f691600160401b9091041686618fb0565b6001600160401b031611156133705760405162461bcd60e51b8152602060048201526046602482015260008051602061953783398151915260448201527f74686520617661696c61626c6520616d6f756e7420696e2063757272656e74206064820152657374616b652160d01b608482015260a401610ade565b60048101546001600160801b9091046001600160401b0316118015906133a257506004810154600160d81b900460ff16155b806133b857506004810154600160d81b900460ff165b6134205760405162461bcd60e51b815260206004820152603360248201527f45746e795374616b696e673a2054686973207374616b652063616e20616363656044820152727074206f6e6c79203120636f6e74726163742160681b6064820152608401610ade565b336000908152601260205260409020546134a25760405162461bcd60e51b815260206004820152603860248201527f45746e795374616b696e673a204e65656420746f2068617665206174206c656160448201527f7374206f6e652062617365207374616b652073657475702100000000000000006064820152608401610ade565b601654336000908152601260205260409020546134c9906001600160401b03871690619272565b11156135215760405162461bcd60e51b8152602060048201526033602482015260008051602061953783398151915260448201527274686520746f74616c206f662037353030302160681b6064820152608401610ade565b6004810154600160d81b900460ff1615156000036135b05760048101546001600160401b038581169116146135b05760405162461bcd60e51b815260206004820152602f60248201527f45746e795374616b696e673a2054686973207374616b696e6720706f6f6c206360448201526e616e6e6f742062652073706c69742160881b6064820152608401610ade565b838160040160088282829054906101000a90046001600160401b03166135d69190618fb0565b82546001600160401b039182166101009390930a9283029282021916919091179091556004830154600160401b810482169116149050801561362357506004810154600160e01b900460ff165b1561363e5760048101805460ff60e81b1916600160e81b1790555b8054600182015460048301546000928392613682926001600160a01b039283169233921690600160c01b810461ffff16908b908d90600160d01b900460ff16617d09565b6003820180546001600160a01b0319166001600160a01b03891617905560048501549193509150600160e01b900460ff16156136ce5760098201805460ff191660011790554260078301555b6009820154600190600685019060009060ff1660048111156136f2576136f261864b565b60048111156137035761370361864b565b815260208101919091526040016000908120805490919061372e9084906001600160401b0316618fb0565b82546101009290920a6001600160401b03818102199093169183160217909155600485018054600160801b90819004831660009081526005880160205260409020859055815460019450919260109261378b928692910416618fb0565b82546101009290920a6001600160401b0381810219909316918316021790915533600081815260116020908152604080832080546001818101835591855283852001889055938352601082528083208054948501815583528183209093018c9055600587015460028801546001600160a01b03168352601290915291812080549290931693509061381d908490619272565b909155505060028201546001600160a01b03166000818152601260209081526040918290205482518b8152918201527f859208af8cfda136750efa35f96dbecdddfae3cf3fe2242c8722870edee6ddde910160405180910390a25060019695505050505050565b6001546000906001600160a01b0316331461389e57600080fd5b50336000908152600e602052604090205490565b6001546000906001600160a01b031633146138cc57600080fd5b600a5482106138ed5760405162461bcd60e51b8152600401610ade90618d9d565b6000600a838154811061390257613902618d20565b6000918252602090912060079091020180549091506001600160a01b0316331461397e5760405162461bcd60e51b815260206004820152602760248201527f45746e795374616b696e673a204f6e6c79207374616b65722063616e2063616c6044820152666c20746869732160c81b6064820152608401610ade565b6000600482810154600160e81b900460ff16908111156139a0576139a061864b565b14806139cb57506003600482810154600160e81b900460ff16908111156139c9576139c961864b565b145b6139e75760405162461bcd60e51b8152600401610ade90618d36565b6003600482810154600160e81b900460ff1690811115613a0957613a0961864b565b03613a80576004810154600160801b90046001600160401b0316613a805760405162461bcd60e51b815260206004820152602860248201527f45746e795374616b696e673a205374616b6520686173206e6f20746f6b656e73604482015267206c6f636b65642160c01b6064820152608401610ade565b60048101546001600160401b03600160401b82048116911611613af95760405162461bcd60e51b815260206004820152602b60248201527f45746e795374616b696e673a20546865726520617265206e6f20746f6b656e7360448201526a20746f20756e6c6f636b2160a81b6064820152608401610ade565b6004810154613b1a906001600160401b03600160401b820481169116618f91565b33600090815260146020526040812080546001600160401b039390931692909190613b46908490618fcf565b9091555050600481018054600160401b81046001600160401b031667ffffffffffffffff199091168117909155158015613b9f57506000600482810154600160e81b900460ff1690811115613b9d57613b9d61864b565b145b15613bbe5760048101805460ff60e81b1916600360e81b179055613bd4565b60048101805460ff60e81b1916600160e81b1790555b33600090815260146020908152604091829020548251868152918201527f1ecc5ef7074a468a8b94f3c0c74cd118529219ec2801efefe9351818a4a46bb2910160405180910390a150600192915050565b6001546001600160a01b03163314613c3c57600080fd5b3360009081526002602052604090205460ff16613c6b5760405162461bcd60e51b8152600401610ade90618c82565b6018805460ff9092166101000261ff0019909216919091179055565b6001546000906001600160a01b03163314613ca157600080fd5b6009548210613cc25760405162461bcd60e51b8152600401610ade90618cd4565b600060098381548110613cd757613cd7618d20565b6000918252602090912060069091020180549091506001600160a01b03163314613d135760405162461bcd60e51b8152600401610ade90619017565b6000600482810154600160501b900460ff1690811115613d3557613d3561864b565b1480613d6057506001600482810154600160501b900460ff1690811115613d5e57613d5e61864b565b145b613d7c5760405162461bcd60e51b8152600401610ade90618d36565b60048101805460ff60501b1916600360501b1790556005810154600b8054600092908110613dac57613dac618d20565b600091825260208220600c909102019150600982015460ff166004811115613dd657613dd661864b565b03613e995760098101805460ff1916600417905542600682018190556008820155600581015481546001600160a01b0316600090815260146020526040812080546001600160401b0390931692909190613e31908490618fcf565b909155505060028101546001600160a01b03166000908152600f6020908152604091829020805460ff19169055600584015491519182527f2b7d80106cf63960f0324ea49c2f7f872886bdfb6cab927918027dd6d0f314f691015b60405180910390a16145fa565b60098101805460ff1990811660031790915542600683015560028201546001600160a01b03166000908152601560209081526040918290208054909316600117909255600584015490519081527fff4d02402ef330920f2f7bfb4a8a15a187a10f1d4f607e9f3d55e6611ef4afe3910160405180910390a160005b60028201546001600160a01b03166000908152601160205260409020548110156144335760028201546001600160a01b03166000908152601160205260408120805483908110613f6657613f66618d20565b906000526020600020015490506000600b8281548110613f8857613f88618d20565b90600052602060002090600c020190506000600a82600a015481548110613fb157613fb1618d20565b6000918252602082206007909102019150600983015460ff166004811115613fdb57613fdb61864b565b1480613fff57506001600983015460ff166004811115613ffd57613ffd61864b565b145b15614089576009820154600190600683019060009060ff1660048111156140285761402861864b565b60048111156140395761403961864b565b81526020810191909152604001600090812080549091906140649084906001600160401b0316618f91565b92506101000a8154816001600160401b0302191690836001600160401b031602179055505b6000600983015460ff1660048111156140a4576140a461864b565b036142155760098201805460ff1916600417905542600683018190556008830155600a820154604080518581526020810192909252600080516020619517833981519152910160405180910390a1600582015460028301546001600160a01b0316600090815260126020526040812080546001600160401b039093169290919061412f908490618fcf565b909155505060058201546004820180546001600160401b0392831692600891614161918591600160401b900416618f91565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555060018160060160008460090160009054906101000a900460ff1660048111156141b0576141b061864b565b60048111156141c1576141c161864b565b81526020810191909152604001600090812080549091906141ec9084906001600160401b0316618fb0565b92506101000a8154816001600160401b0302191690836001600160401b031602179055506143aa565b6001600983015460ff1660048111156142305761423061864b565b036143aa5760098201805460ff191660031790554260068301556005820154600783015460405163d83102cd60e01b815261ffff600160801b90930492909216600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af41580156142b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142da9190618d84565b60088301556009820154600190600683019060009060ff1660048111156143035761430361864b565b60048111156143145761431461864b565b815260208101919091526040016000908120805490919061433f9084906001600160401b0316618fb0565b92506101000a8154816001600160401b0302191690836001600160401b031602179055507fb503cf14e3d55841fd2c9a549abd732f6898fde969da012639aa917173e3a0068383600a01546040516143a1929190918252602082015260400190565b60405180910390a15b8160080154856008015410156143c557600880830154908601555b6001600482810154600160e81b900460ff16908111156143e7576143e761864b565b14801561440d5750600160009081526006820160205260409020546001600160401b0316155b156144285760048101805460ff60e81b1916600360e81b1790555b505050600101613f14565b5080600801546000036145fa5760195460058201546001600160401b03600160801b9092048216911610156145675760098101805460ff1916600417905542600682018190556008820155600581015481546001600160a01b0316600090815260146020526040812080546001600160401b03909316929091906144b8908490618fcf565b90915550506002810180546001600160a01b039081166000908152600f60209081526040808320805460ff1990811690915585548516845260158352818420805490911690556005860154945490931682526012905290812080546001600160401b039093169290919061452d908490618fcf565b909155505060058201546040519081527f2b7d80106cf63960f0324ea49c2f7f872886bdfb6cab927918027dd6d0f314f690602001613e8c565b6005810154600782015460405163d83102cd60e01b8152600160801b90920461ffff16600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af41580156145d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145f49190618d84565b60088201555b5060019392505050565b60008060008060008060008060008060006009805490508d106146395760405162461bcd60e51b8152600401610ade90618cd4565b600060098e8154811061464e5761464e618d20565b906000526020600020906006020190508c6001600160401b03166000146146875760405162461bcd60e51b8152600401610ade90618ded565b6000816005015490506000600b82815481106146a5576146a5618d20565b90600052602060002090600c020190508f8f838560000160009054906101000a90046001600160a01b03168460020160009054906101000a90046001600160a01b03168560030160009054906101000a90046001600160a01b031686600401548760050160009054906101000a90046001600160401b03168860050160109054906101000a900461ffff168960090160009054906101000a900460ff168a600801548261ffff1692509d509d509d509d509d509d509d509d509d509d509d505050509295989b509295989b9093969950565b6001546000906001600160a01b0316331461479157600080fd5b503360009081526010602052604090205490565b6001546000906001600160a01b031633146147bf57600080fd5b506019546001600160401b031690565b6001546000906001600160a01b031633146147e957600080fd5b600954821061480a5760405162461bcd60e51b8152600401610ade90618cd4565b60006009838154811061481f5761481f618d20565b6000918252602090912060069091020160028101549091506001600160a01b031633146148b45760405162461bcd60e51b815260206004820152603960248201527f45746e795374616b696e673a204f6e6c79206e6f6465206f70657261746f722060448201527f63616e206465636c696e652074686973207265717565737421000000000000006064820152608401610ade565b6000600482810154600160501b900460ff16908111156148d6576148d661864b565b146148f35760405162461bcd60e51b8152600401610ade90618d36565b60048101805460ff60501b1916600160511b1790556005810154600b805460009290811061492357614923618d20565b600091825260208083206009600c90930201918201805460ff19166002179055600582015482546001600160a01b0316845260149091526040832080549294506001600160401b0390911692909161497c908490618fcf565b9091555050336000908152601260209081526040808320839055600f9091529020805460ff191690555060019392505050565b6001546001600160a01b031633146149c657600080fd5b3360009081526002602052604090205460ff166149f55760405162461bcd60e51b8152600401610ade90618c82565b601880546001600160401b03909216600160501b0267ffffffffffffffff60501b19909216919091179055565b6000546201000090046001600160a01b03163314614a525760405162461bcd60e51b8152600401610ade90618fe2565b6001600160a01b03166000908152600260205260409020805460ff19169055565b600080600080600080600080600080600a805490508c10614aa65760405162461bcd60e51b8152600401610ade90618d9d565b6000600a8d81548110614abb57614abb618d20565b906000526020600020906007020190508060040160109054906101000a90046001600160401b03166001600160401b03168c6001600160401b031610614b135760405162461bcd60e51b8152600401610ade90618ded565b6001600160401b038c166000908152600582016020526040812054600b805491929183908110614b4557614b45618d20565b600091825260208220919550600c020190506001600982015460ff166004811115614b7257614b7261864b565b03614c0b576005810154600782015460405163d83102cd60e01b8152600160801b90920461ffff16600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af4158015614be0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c049190618d84565b9350614c13565b806008015493505b8e8e838560000160009054906101000a90046001600160a01b03168460020160009054906101000a90046001600160a01b031685600401548660050160009054906101000a90046001600160401b03168760050160109054906101000a900461ffff168860090160009054906101000a900460ff168c8261ffff1692509c509c509c509c509c509c509c509c509c509c505050509295989b9194979a5092959850565b6001546000906001600160a01b03163314614cd057600080fd5b600a548310614cf15760405162461bcd60e51b8152600401610ade90618d9d565b6000600a8481548110614d0657614d06618d20565b906000526020600020906007020190508060040160109054906101000a90046001600160401b03166001600160401b0316836001600160401b031610614d5e5760405162461bcd60e51b8152600401610ade90618ded565b6001600160401b0383166000908152600582016020526040812054600b805491929183908110614d9057614d90618d20565b600091825260208220600c909102019150600982015460ff166004811115614dba57614dba61864b565b14614e2d5760405162461bcd60e51b815260206004820152603c60248201527f45746e795374616b696e673a204f6e6c792070656e64696e67207374616b696e60448201527f6720636f6e7472616374732063616e206265206465636c696e656421000000006064820152608401610ade565b6009810154600190600685019060009060ff166004811115614e5157614e5161864b565b6004811115614e6257614e6261864b565b8152602081019190915260400160009081208054909190614e8d9084906001600160401b0316618f91565b82546101009290920a6001600160401b0381810219909316918316021790915560098301805460ff19166002908117909155600090815260068601602052604081208054600194509092614ee391859116618fb0565b82546101009290920a6001600160401b038181021990931691831602179091556005830154600486018054918316935091600891614f2a918591600160401b900416618f91565b82546101009290920a6001600160401b03818102199093169183160217909155600583015460028401546001600160a01b03166000908152601260205260408120805492909316935090614f7f908490618fcf565b909155505060028301546001600160a01b031615614fec5760048301805460ff60e81b1916600160e91b179055600581015481546001600160a01b0316600090815260146020526040812080546001600160401b0390931692909190614fe6908490618fcf565b90915550505b60408051838152602081018890527fa6d35207a3d1012ac29345fe2aeabf0b1dc6285e13a1dbca53d5738524323a54910160405180910390a150600195945050505050565b6001546000906001600160a01b0316331461504b57600080fd5b5060165490565b6001546000906001600160a01b0316331461506c57600080fd5b3360009081526002602052604090205460ff1615156001146150a05760405162461bcd60e51b8152600401610ade90619285565b600b5483106150c15760405162461bcd60e51b8152600401610ade90618e3a565b6000600b84815481106150d6576150d6618d20565b60009182526020909120600c9091020190506003600982015460ff1660048111156151035761510361864b565b146151205760405162461bcd60e51b8152600401610ade90619172565b428160080154106151435760405162461bcd60e51b8152600401610ade906191c5565b6001600b82015460ff16600181111561515e5761515e61864b565b036151715761516c846129bf565b6145fa565b61517d84846001616825565b505060019392505050565b6001546000906001600160a01b031633146151a257600080fd5b3360009081526002602052604090205460ff1615156001146151d65760405162461bcd60e51b8152600401610ade90618e7e565b6000600a83815481106151eb576151eb618d20565b600091825260208220600460079092020190810180549193509060ff60e81b1916600160e81b83611ac5565b6001546001600160a01b0316331461522e57600080fd5b3360009081526002602052604090205460ff1661525d5760405162461bcd60e51b8152600401610ade90618c82565b600780546001600160a01b0319166001600160a01b0392909216919091179055565b6001546000906001600160a01b0316331461529957600080fd5b6007546001600160a01b03166152c15760405162461bcd60e51b8152600401610ade906192f6565b6001600160a01b03841661532d5760405162461bcd60e51b815260206004820152602d60248201527f45746e795374616b696e673a206e6f646520616464726573732069732074686560448201526c207a65726f206164647265737360981b6064820152608401610ade565b6001600160a01b03841633036153b55760405162461bcd60e51b815260206004820152604160248201527f45746e795374616b696e673a20546865206e6f64652061646472657373206d7560448201527f737420626520646966666572656e74207468616e2063757272656e74206f6e656064820152602160f81b608482015260a401610ade565b601854610100900460ff1661ffff831610156154265760405162461bcd60e51b815260206004820152602a60248201527f45746e795374616b696e673a20546865207374616b696e6720706572696f6420604482015269697320746f206c6f772160b01b6064820152608401610ade565b6018546001600160401b03600160501b90910481169084161080159061546257506019546001600160401b03600160401b909104811690841611155b6154d45760405162461bcd60e51b815260206004820152603f60248201527f45746e795374616b696e673a20616d6f756e74206d757374206265206265747760448201527f65656e206d696e696d756d20616e64206d6178696d756d2076616c75657321006064820152608401610ade565b6001600160a01b0384166000908152601260205260409020541561550a5760405162461bcd60e51b8152600401610ade90619386565b6001600160a01b0384166000908152600f602052604090205460ff16156155435760405162461bcd60e51b8152600401610ade90619386565b600061554e85617f86565b9050801561556e5760405162461bcd60e51b8152600401610ade906193db565b600061557933617f86565b336000908152601460205260409020549091506001600160401b038616906155a19083618fcf565b10156155bf5760405162461bcd60e51b8152600401610ade9061941d565b336000818152600c60209081526040808320600980548254600180820185559387528587200155546001600160a01b038c168552600e84528285208054928301815585529383902001839055518281529195507fd7490e816438b23e3486aef50b4dfd914be81021d62b1db81226227291f6c85b910160405180910390a260008061565133896000898b8a6064617d09565b600b8201805492945090925060009160ff1916600183021790555060408051610100810182523381526000602082018190526001600160a01b038b16928201929092524260608201526001600160401b038916608082015261ffff881660a082015260099160c082019081526020908101849052825460018082018555600094855293829020835160069092020180546001600160a01b03199081166001600160a01b03938416178255928401519481018054841695831695909517909455604083015160028501805490931691161790556060810151600383015560808101516004808401805460a08501516001600160401b0390941669ffffffffffffffffffff1990911617600160401b61ffff909416939093029290921780835560c0840151939493929160ff60501b1990911690600160501b90849081111561579a5761579a61864b565b021790555060e0919091015160059091015533600090815260146020526040812080546001600160401b038a1692906157d4908490619272565b9091555050506001600160a01b0387166000908152600f60205260409020805460ff191660011790555050509392505050565b6001546000906001600160a01b0316331461582157600080fd5b6007546001600160a01b03166158495760405162461bcd60e51b8152600401610ade906192f6565b8360ff166064146158c2576001600160a01b0386166158c25760405162461bcd60e51b815260206004820152602f60248201527f45746e795374616b696e673a207265776172642061646472657373206973207460448201526e6865207a65726f206164647265737360881b6064820152608401610ade565b6019546001600160401b03908116908816101561592d5760405162461bcd60e51b815260206004820152602360248201527f45746e795374616b696e673a2054686520616d6f756e7420697320746f30206c6044820152626f772160e81b6064820152608401610ade565b601854610100900460ff1661ffff861610156159965760405162461bcd60e51b815260206004820152602260248201527f45746e795374616b696e673a2054686520706572696f6420697320746f206c6f604482015261772160f01b6064820152608401610ade565b60658460ff1610615a0f5760405162461bcd60e51b815260206004820152603860248201527f45746e795374616b696e673a20546865206f70657261746f722072657761726460448201527f2070657263656e7461676520697320746f6f20686967682100000000000000006064820152608401610ade565b336001600160a01b03871603615a9f5760405162461bcd60e51b815260206004820152604960248201527f45746e795374616b696e673a205468652063757272656e74206164647265737360448201527f2073686f756c6420626520646966666572656e74207468616e2072657761726460648201526820616464726573732160b81b608482015260a401610ade565b6001600160a01b03881615615d39576001600160a01b03881660009081526015602052604090205460ff1615615b3d5760405162461bcd60e51b815260206004820152603e60248201527f45746e795374616b696e673a205468652062617365207374616b6520636f6e7460448201527f72616374206f6e20746865206e6f6465207761732063616e63656c65642100006064820152608401610ade565b6001600160a01b038816600090815260126020526040902054615bc85760405162461bcd60e51b815260206004820152603860248201527f45746e795374616b696e673a20546865206e6f646520646f65736e277420686160448201527f766520616e792062617365207374616b652073657475702100000000000000006064820152608401610ade565b6001600160a01b0388163303615c395760405162461bcd60e51b815260206004820152603060248201527f45746e795374616b696e673a20546865206e6f64652061646472657373206d7560448201526f737420626520646966666572656e742160801b6064820152608401610ade565b876001600160a01b0316866001600160a01b031603615c6a5760405162461bcd60e51b8152600401610ade90619468565b6016546001600160a01b038916600090815260126020526040902054615c9a906001600160401b038a1690619272565b1115615d0c5760405162461bcd60e51b8152602060048201526047602482015260008051602061953783398151915260448201527f746865206d6178696d756d20616c6c6f77656420746f6b656e73206f6e20746860648201526665206e6f64652160c81b608482015260a401610ade565b6000615d1789617f86565b90508015615d375760405162461bcd60e51b8152600401610ade906193db565b505b6000615d4433617f86565b336000908152601460205260409020549091506001600160401b03891690615d6c9083618fcf565b1015615d8a5760405162461bcd60e51b8152600401610ade9061941d565b6000600a6001816001815401808255809150500390600052602060002090600702019050338160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550878160010160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550898160020160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550428160030181905550888160040160006101000a8154816001600160401b0302191690836001600160401b0316021790555060008160040160086101000a8154816001600160401b0302191690836001600160401b0316021790555060008160040160106101000a8154816001600160401b0302191690836001600160401b03160217905550868160040160186101000a81548161ffff021916908361ffff1602179055508581600401601a6101000a81548160ff021916908360ff1602179055508481600401601b6101000a81548160ff0219169083151502179055508381600401601c6101000a81548160ff021916908315150217905550600081600401601d6101000a81548160ff02191690836004811115615f4a57615f4a61864b565b0217905550600a54615f5e90600190618fcf565b60405181815290935033907ffb7b213a27fb2f9ada24dbc107b98a959d208d5a39fb37f481b80ff7cc4ec4b49060200160405180910390a2336000908152600d60209081526040822080546001810182559083529120018390556001600160a01b038a16156161555780546000908190615fe6906001600160a01b03168d8c8c8f8a8e617d09565b60098201549193509150600190600685019060009060ff16600481111561600f5761600f61864b565b60048111156160205761602061864b565b815260208101919091526040016000908120805490919061604b9084906001600160401b0316618fb0565b82546101009290920a6001600160401b03818102199093169183160217909155600485018054600160801b9081900483166000908152600588016020526040902085905581546001945091926010926160a8928692910416618fb0565b82546101009290920a6001600160401b0381810219909316918316021790915560048501805467ffffffffffffffff60401b1916600160401b928f169283021790556001600160a01b038e166000818152601060209081526040808320805460018181018355918552838520018c905584845260118352818420805491820181558452828420018790559282526012905290812080549293509161614d908490619272565b909155505050505b33600090815260146020526040812080546001600160401b038c16929061617d908490619272565b90915550505050979650505050505050565b6001546060906001600160a01b031633146161a957600080fd5b3360009081526010602090815260409182902080548351818402810184019094528084529091830182828015612450576020028201919060005260206000209081548152602001906001019080831161243c575050505050905090565b6001546000906001600160a01b0316331461622057600080fd5b50601854600160501b90046001600160401b031690565b6001546000906001600160a01b0316331461625157600080fd5b5060185460ff1690565b6001546001600160a01b0316331461627257600080fd5b3360009081526002602052604090205460ff166162a15760405162461bcd60e51b8152600401610ade90618c82565b601980546001600160401b03909216600160401b0267ffffffffffffffff60401b19909216919091179055565b6001600160a01b0381166000908152600e60209081526040808320600f83528184205460128452828520546015855283862054835485518188028101880190965280865260609796879687969560ff90811695941692909186919083018282801561635857602002820191906000526020600020905b815481526020019060010190808311616344575b5050505050935093509350935093509193509193565b6001546000906001600160a01b0316331461638857600080fd5b50600a5490565b60015460009081908190819081906001600160a01b031633146163b157600080fd5b600b5486106163d25760405162461bcd60e51b8152600401610ade90618e3a565b6000600b87815481106163e7576163e7618d20565b600091825260208220919450600c020190506001600982015460ff1660048111156164145761641461864b565b036164ad576005810154600782015460405163d83102cd60e01b8152600160801b90920461ffff16600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af4158015616482573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906164a69190618d84565b92506164b5565b806008015492505b600481015460078201546008830154600690930154919990985091965092945091925050565b6001546000906001600160a01b031633146164f557600080fd5b336000908152600e602052604090205482106165235760405162461bcd60e51b8152600401610ade90618e3a565b336000908152600e6020526040902080548390811061101a5761101a618d20565b6001546000906001600160a01b0316331461655e57600080fd5b3360009081526002602052604090205460ff1615156001146165f25760405162461bcd60e51b815260206004820152605360248201526000805160206194f783398151915260448201527f6573732063616e207465726d696e61746520612042617365205374616b6520616064820152726e64206170706c792070656e616c746965732160681b608482015260a401610ade565b600b5482106166135760405162461bcd60e51b8152600401610ade90618ec9565b6000600b838154811061662857616628618d20565b90600052602060002090600c020190506000600982600a01548154811061665157616651618d20565b9060005260206000209060060201905064012117d1578260080154106166df5760405162461bcd60e51b815260206004820152603860248201527f45746e795374616b696e673a2054686520636f6e74726163742077617320616c60448201527f72656164792070726f6c6f6e67656420666f72657665722100000000000000006064820152608401610ade565b6166e881618013565b600982018054600360ff199182161790915542600684015564012117d15760088401556002830180546001600160a01b03908116600090815260156020908152604080832080548716600190811790915594549093168252600f90522080549092161790556167568261802f565b60028201546001600160a01b03166000908152601260209081526040918290205491519182527f1fe3c8d9b22341d7ceb24f6a7806432c03c741b526bec20edf6a49bc22b20bc2910160405180910390a15060019392505050565b6001546000906001600160a01b031633146167cb57600080fd5b50600b5490565b6001546000906001600160a01b031633146167ec57600080fd5b506007546001600160a01b031690565b6001546000906001600160a01b0316331461681657600080fd5b50601854610100900460ff1690565b6001546000906001600160a01b0316331461683f57600080fd5b3360009081526002602052604090205460ff1615156001146168735760405162461bcd60e51b8152600401610ade90619285565b600b5484106168945760405162461bcd60e51b8152600401610ade90618e3a565b6000600b85815481106168a9576168a9618d20565b600091825260208220600c909102019150600b82015460ff1660018111156168d3576168d361864b565b1461693b5760405162461bcd60e51b815260206004820152603260248201527f45746e795374616b696e673a20412042617365205374616b6520436f6e74726160448201527163742069642069732065787065637465642160701b6064820152608401610ade565b6003600982015460ff1660048111156169565761695661864b565b146169735760405162461bcd60e51b8152600401610ade90619172565b82156169825761698281618184565b428160080154106169a55760405162461bcd60e51b8152600401610ade906191c5565b6000600982600a0154815481106169be576169be618d20565b906000526020600020906006020190506169d78261822d565b84616ac75760028201546005830154616a02916001600160a01b0316906001600160401b0316617aaa565b600982018054600460ff1991821617909155426006840181905560088401556002830180546001600160a01b03908116600090815260156020908152604080832080548716905593549092168152600f909152208054909116905581546004820154616a80916001600160a01b0316906001600160401b03166179cd565b616a8981618427565b6040518681527f2b7d80106cf63960f0324ea49c2f7f872886bdfb6cab927918027dd6d0f314f69060200160405180910390a1600192505050610f5f565b60006006830181905560028301546001600160a01b03168152601560205260409020805460ff191690556004810180546001919060ff60501b1916600160501b8302179055506009820180546001919060ff1916828002179055506005820154600783015460405163d83102cd60e01b8152600160801b90920461ffff16600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af4158015616b8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190616baf9190618d84565b60088301556040518681527f36e5b23050bb3a750f3648961be392c7f7ddad7be9d63439307a6381168b3a049060200160405180910390a150600195945050505050565b6001546000906001600160a01b03163314616c0d57600080fd5b50336000908152600c602052604090205490565b6001546000906001600160a01b03163314616c3b57600080fd5b6009548310616c5c5760405162461bcd60e51b8152600401610ade90618cd4565b6001600160a01b038216616c825760405162461bcd60e51b8152600401610ade90619222565b336001600160a01b03831603616caa5760405162461bcd60e51b8152600401610ade90619468565b600060098481548110616cbf57616cbf618d20565b6000918252602090912060069091020160028101549091506001600160a01b03163314616d545760405162461bcd60e51b815260206004820152603760248201527f45746e795374616b696e673a206f6e6c79206e6f6465206f70657261746f722060448201527f63616e20617070726f76652062617365207374616b65210000000000000000006064820152608401610ade565b6000600482810154600160501b900460ff1690811115616d7657616d7661864b565b14616dda5760405162461bcd60e51b815260206004820152602e60248201527f45746e795374616b696e673a207374616b65206d757374206265206e6577207460448201526d6f20626520617070726f7665642160901b6064820152608401610ade565b60048101805460ff60501b1916600160501b1790556001810180546001600160a01b0319166001600160a01b0385161790556005810154600b8054600092908110616e2757616e27618d20565b600091825260208083206009600c90930201918201805460ff191660011790554260078301556003820180546001600160a01b0389166001600160a01b0319909116179055600582015433845260129091526040832080549294506001600160401b03909116929091616e9b908490619272565b909155505033600090815260126020908152604091829020548251888152918201527f1dbef83c751dbba35b43f07c7ba982ca00b3627cd0d733b6c55870a6ea4bce56910160405180910390a1506001949350505050565b6001600160a01b0381166000908152600e6020908152604091829020805483518184028101840190945280845260609392830182828015616f5357602002820191906000526020600020905b815481526020019060010190808311616f3f575b50505050509050919050565b6001546001600160a01b03163314616f7657600080fd5b3360009081526002602052604090205460ff16616fa55760405162461bcd60e51b8152600401610ade90618c82565b601755565b6001546000906001600160a01b03163314616fc457600080fd5b336000908152601060205260409020548210616ff25760405162461bcd60e51b8152600401610ade90618e3a565b33600090815260106020526040902080548390811061101a5761101a618d20565b6001546000906001600160a01b0316331461702d57600080fd5b50601954600160401b90046001600160401b031690565b600080600080600080600080600080600080600080600a8f8154811061706c5761706c618d20565b906000526020600020906007020190508e8160000160009054906101000a90046001600160a01b03168260010160009054906101000a90046001600160a01b03168360020160009054906101000a90046001600160a01b031684600301548560040160009054906101000a90046001600160401b03168660040160089054906101000a90046001600160401b03168760040160189054906101000a900461ffff1688600401601a9054906101000a900460ff1689600401601b9054906101000a900460ff168a600401601c9054906101000a900460ff168b600401601d9054906101000a900460ff168c60040160109054906101000a90046001600160401b03168561ffff1695509d509d509d509d509d509d509d509d509d509d509d509d509d505091939597999b9d90929496989a9c50565b6000546201000090046001600160a01b031633146171d05760405162461bcd60e51b8152600401610ade90618fe2565b6001600160a01b0381166172355760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610ade565b600080546040516001600160a01b03808516936201000090930416917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b6001546000906001600160a01b031633146172b857600080fd5b3360009081526002602052604090205460ff166172e75760405162461bcd60e51b8152600401610ade90618c82565b600b5484106173085760405162461bcd60e51b8152600401610ade90618e3a565b6000600b858154811061731d5761731d618d20565b600091825260209091206003600c90920201908101549091506001600160a01b0385811691161461739e5760405162461bcd60e51b815260206004820152602560248201527f45746e795374616b696e673a2072657761726420616464726573732070726f76604482015264696465642160d81b6064820152608401610ade565b60030180546001600160a01b0384166001600160a01b03199091161790555060019392505050565b6001546000906001600160a01b031633146173e057600080fd5b60006173eb33617f86565b336000908152601460205260409020549091506174089082618fcf565b91505090565b6001546000906001600160a01b0316331461742857600080fd5b6000600985015460ff1660048111156174435761744361864b565b148061746757506001600985015460ff1660048111156174655761746561864b565b145b6174ea5760405162461bcd60e51b815260206004820152604860248201527f45746e795374616b696e673a204f6e6c792070656e64696e67206f722061707060448201527f726f766564207374616b696e6720636f6e7472616374732063616e2062652063606482015267616e63656c65642160c01b608482015260a401610ade565b83546001600160a01b031633148061750e575060028401546001600160a01b031633145b8061752d57503360009081526002602052604090205460ff1615156001145b6175c55760405162461bcd60e51b815260206004820152605760248201527f45746e795374616b696e673a204f6e6c79207374616b65686f6c6465722c206e60448201527f6f6465206f70657261746f72206f7220636f6d70616e7961646472657373206360648201527f616e2063616e63656c2074686520636f6e747261637421000000000000000000608482015260a401610ade565b6009840154600190600687019060009060ff1660048111156175e9576175e961864b565b60048111156175fa576175fa61864b565b81526020810191909152604001600090812080549091906176259084906001600160401b0316618f91565b92506101000a8154816001600160401b0302191690836001600160401b031602179055506000600481111561765c5761765c61864b565b600985015460ff1660048111156176755761767561864b565b036177c05760098401805460ff1916600417905542600685018190556008850155600a840154604080518581526020810192909252600080516020619517833981519152910160405180910390a160058401546004860180546001600160401b03928316926008916176f0918591600160401b900416618f91565b82546101009290920a6001600160401b03818102199093169183160217909155600586015460028701546001600160a01b03166000908152601260205260408120805492909316935090617745908490618fcf565b909155505060028501546001600160a01b0316156177bb576004850180546001600160801b0360ff60e81b011916600160ea1b179055600584015484546001600160a01b0316600090815260146020526040812080546001600160401b03909316929091906177b5908490618fcf565b90915550505b61793d565b6001600985015460ff1660048111156177db576177db61864b565b0361793d573360009081526002602052604090205460ff16151560010361780c57617807858585618440565b6178f6565b60098401805460ff191660031790554260068501556005840154600785015460405163d83102cd60e01b815261ffff600160801b90930492909216600483015260248201527322a56c5971102a09980e7c3c9b288a09f77500c29063d83102cd90604401602060405180830381865af415801561788d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906178b19190618d84565b6008850155600a8401546040805185815260208101929092527fb503cf14e3d55841fd2c9a549abd732f6898fde969da012639aa917173e3a006910160405180910390a15b83546001600160a01b031633148061792257503360009081526002602052604090205460ff1615156001145b1561793d57600b8401805461ff001916610100841515021790555b6009840154600190600687019060009060ff1660048111156179615761796161864b565b60048111156179725761797261864b565b815260208101919091526040016000908120805490919061799d9084906001600160401b0316618fb0565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555060019050949350505050565b6001600160a01b0382166000908152601460205260409020546001600160401b0382161115617a705760405162461bcd60e51b815260206004820152604360248201527f496e73756666696369656e74207374616b6520686f6c646572206c6f636b656460448201527f20746f6b656e7320696e207374616b696e6720666f722073756274726163746960648201526237b71760e91b608482015260a401610ade565b6001600160a01b038216600090815260146020526040812080546001600160401b0384169290617aa1908490618fcf565b90915550505050565b6001600160a01b0382166000908152601260205260409020546001600160401b0382161115617b345760405162461bcd60e51b815260206004820152603060248201527f496e73756666696369656e74206e6f6465207374616b656420746f6b656e732060448201526f3337b91039bab13a3930b1ba34b7b71760811b6064820152608401610ade565b6001600160a01b038216600090815260126020526040812080546001600160401b0384169290617aa1908490618fcf565b6009830154600190600684019060009060ff166004811115617b8957617b8961864b565b6004811115617b9a57617b9a61864b565b8152602081019190915260400160009081208054909190617bc59084906001600160401b0316618f91565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550808360090160006101000a81548160ff02191690836004811115617c0f57617c0f61864b565b02179055506009830154600190600684019060009060ff166004811115617c3857617c3861864b565b6004811115617c4957617c4961864b565b8152602081019190915260400160009081208054909190617c749084906001600160401b0316618fb0565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550505050565b6001600482810154600160e81b900460ff1690811115617cbf57617cbf61864b565b148015617ce357506004810154600160401b81046001600160401b03908116911614155b15617d06576004810180546000919060ff60e81b1916600160e81b835b02179055505b50565b600b8054600180820183556000928352600c82027f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9810180546001600160a01b039c8d166001600160a01b03199182161782557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbb830180549c8e169c82169c909c17909b557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dba820180549a909c16998b1699909917909a557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbc8a018054909916909855427f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbd8a01557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbe890180547f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbf8b018490557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dc18b018490557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dc08b01939093557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dc38a01949094557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dc28901805460ff199081169091557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dc49099018054909916909717909755600160401b60ff9091160261ffff93909316600160801b0271ffff0000000000000000ffffffffffffffff199096166001600160401b0392909216919091179490941767ffffffffffffffff60401b1916179092559091565b6000601281617f9682600a61914f565b6007546040516370a0823160e01b81526001600160a01b0387811660048301529293508392909116906370a0823190602401602060405180830381865afa158015617fe5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906180099190618d84565b61236691906194d4565b6004810180546003919060ff60501b1916600160501b83617d00565b60005b60028201546001600160a01b03166000908152601160205260409020548110156181805760028201546001600160a01b0316600090815260116020526040812080548390811061808457618084618d20565b906000526020600020015490506000600b82815481106180a6576180a6618d20565b90600052602060002090600c020190506000600a82600a0154815481106180cf576180cf618d20565b6000918252602090912060079091020190506003600983015460ff1660048111156180fc576180fc61864b565b036181225761810c818385618440565b600b8201805461ff001916610100179055618175565b6000600983015460ff16600481111561813d5761813d61864b565b148061816157506001600983015460ff16600481111561815f5761815f61864b565b145b1561817557618173818385600161740e565b505b505050600101618032565b5050565b60005b60028201546001600160a01b03166000908152601160205260409020548110156181805760028201546001600160a01b031660009081526011602052604081208054839081106181d9576181d9618d20565b906000526020600020015490506000600b82815481106181fb576181fb618d20565b90600052602060002090600c0201600801549050808460080154101561822357600884018190555b5050600101618187565b60005b60028201546001600160a01b03166000908152601160205260409020548110156181805760028201546001600160a01b0316600090815260116020526040812080548390811061828257618282618d20565b906000526020600020015490506000600b82815481106182a4576182a4618d20565b90600052602060002090600c020190506000600a82600a0154815481106182cd576182cd618d20565b6000918252602090912060079091020190506003600983015460ff1660048111156182fa576182fa61864b565b14801561830a5750428260080154105b15618413576183198282618615565b8154600583015461833c916001600160a01b0316906001600160401b03166179cd565b60028201546005830154618362916001600160a01b0316906001600160401b0316617aaa565b60058201546004820180546001600160401b039283169260089161838f918591600160401b900416618f91565b82546001600160401b039182166101009390930a92830291909202199091161790555060028101546001600160a01b0316156184135760048101805460ff60e81b1916600160ea1b179055600a8201546040519081527fa002debc9839c20f8a9424b3c4bad3295abbb3676c3acf6ea94d869f6b4f54c09060200160405180910390a15b61841c81617c9d565b505050600101618230565b6004818101805460ff60501b1916600160501b83617d00565b60098201805460ff191660049081179091554260068401819055600880850191909155600584015491850180546001600160401b0393841693919291618490918591600160401b90910416618f91565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550600160048111156184c7576184c761864b565b600484810154600160e81b900460ff16908111156184e7576184e761864b565b036184fc5760048301805460ff60e81b191690555b600582015460028301546001600160a01b0316600090815260126020526040812080546001600160401b0390931692909190618539908490618fcf565b9091555050600a820154604080518381526020810192909252600080516020619517833981519152910160405180910390a160028301546001600160a01b031615618610576004830180546001600160801b0360ff60e81b011916600160ea1b179055600582015482546001600160a01b0316600090815260146020526040812080546001600160401b03909316929091906185d6908490618fcf565b9091555050600a8201546040519081527fa002debc9839c20f8a9424b3c4bad3295abbb3676c3acf6ea94d869f6b4f54c090602001612cbd565b505050565b61862182826004617b65565b504260068201819055600890910155565b60006020828403121561864457600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60058110617d0657617d0661864b565b61867a81618661565b9052565b6002811061867a5761867a61864b565b8b81526001600160a01b038b811660208301528a8116604083015289811660608301528816608082015260a081018790526001600160401b0386811660c083015285811660e0830152841661010082015261016081016186f2610120830185618671565b61870061014083018461867e565b9c9b505050505050505050505050565b80356001600160401b0381168114610bd757600080fd5b80358015158114610bd757600080fd5b60008060006060848603121561874c57600080fd5b8335925061875c60208501618710565b915061876a60408501618727565b90509250925092565b6000806000806080858703121561878957600080fd5b5050823594602084013594506040840135936060013592509050565b80356001600160a01b0381168114610bd757600080fd5b600080604083850312156187cf57600080fd5b6187d8836187a5565b91506187e660208401618710565b90509250929050565b60008060006060848603121561880457600080fd5b8335925061881460208501618710565b915061876a604085016187a5565b60006020828403121561883457600080fd5b610f5f826187a5565b60006020828403121561884f57600080fd5b610f5f82618710565b803560ff81168114610bd757600080fd5b60006020828403121561887b57600080fd5b610f5f82618858565b600081518084526020840193506020830160005b828110156188b6578151865260209586019590910190600101618898565b5093949350505050565b602081526000610f5f6020830184618884565b8981526001600160a01b038981166020830152888116604083015287166060820152608081018690526001600160401b0385811660a0830152841660c0820152610120810161892184618661565b8360e083015261893561010083018461867e565b9a9950505050505050505050565b6000806040838503121561895657600080fd5b823591506187e660208401618710565b8b81526001600160401b038b81166020830152604082018b90526001600160a01b038a811660608401528981166080840152881660a083015260c0820187905285811660e0830152841661010082015261016081016189c9610120830185618671565b826101408301529c9b505050505050505050505050565b8a81526001600160401b038a81166020830152604082018a90526001600160a01b0389811660608401528816608083015260a0820187905285811660c0830152841660e08201526101408101618a3584618661565b610100820193909352610120015298975050505050505050565b60008060408385031215618a6257600080fd5b823591506187e660208401618727565b803561ffff81168114610bd757600080fd5b600080600060608486031215618a9957600080fd5b618aa2846187a5565b9250618ab060208501618710565b915061876a60408501618a72565b600080600080600080600060e0888a031215618ad957600080fd5b618ae2886187a5565b9650618af060208901618710565b9550618afe604089016187a5565b9450618b0c60608901618a72565b9350618b1a60808901618858565b9250618b2860a08901618727565b9150618b3660c08901618727565b905092959891949750929550565b608081526000618b576080830187618884565b94151560208301525060408101929092521515606090910152919050565b600080600060608486031215618b8a57600080fd5b8335925061875c60208501618727565b60008060408385031215618bad57600080fd5b823591506187e6602084016187a5565b8d81526001600160a01b038d811660208301528c811660408301528b166060820152608081018a90526001600160401b0389811660a0830152881660c08201526101a081016001600160401b03881660e083015260ff8716610100830152851515610120830152841515610140830152618c3b610160830185618671565b6001600160401b0383166101808301529e9d5050505050505050505050505050565b600080600060608486031215618c7257600080fd5b83359250618814602085016187a5565b60208082526032908201527f436f6d70616e7957616c6c65743a2063616c6c6572206973206e6f7420612077604082015271616c6c65742066726f6d20636f6d70616e7960701b606082015260800190565b6020808252602c908201527f45746e795374616b696e673a20496e76616c69642042617365205374616b652060408201526b49442070726f76696465642160a01b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b6020808252602e908201527f45746e795374616b696e673a205374616b6520697320686176696e672064696660408201526d666572656e74207374617475732160901b606082015260800190565b600060208284031215618d9657600080fd5b5051919050565b60208082526030908201527f45746e795374616b696e673a20496e76616c696420457874656e64656420537460408201526f616b652049442070726f76696465642160801b606082015260800190565b6020808252602d908201527f45746e795374616b696e673a20496e76616c6964205374616b6520436f6e747260408201526c6163742070726f76696465642160981b606082015260800190565b60208082526024908201527f45746e795374616b696e673a20496e76616c696420496e6465782070726f76696040820152636465642160e01b606082015260800190565b6020808252603c908201526000805160206194f783398151915260408201527f6573732063616e20706572666f726d207468697320616374696f6e2100000000606082015260800190565b60208082526035908201527f45746e795374616b696e673a20496e76616c69642042617365205374616b6520604082015274436f6e74726163742049442070726f76696465642160581b606082015260800190565b6020808252603f908201527f45746e795374616b696e673a205468652062617365207374616b6520636f6e7460408201527f72616374206f6e2074686973206e6f6465207761732063616e63656c65642100606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6001600160401b03828116828216039081111561128a5761128a618f7b565b6001600160401b03818116838216019081111561128a5761128a618f7b565b8181038181111561128a5761128a618f7b565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f45746e795374616b696e673a204f6e6c79207374616b65722063616e2063616e60408201527063656c207468697320726571756573742160781b606082015260800190565b6001815b60018411156190a35780850481111561908757619087618f7b565b600184161561909557908102905b60019390931c92800261906c565b935093915050565b6000826190ba5750600161128a565b816190c75750600061128a565b81600181146190dd57600281146190e757619103565b600191505061128a565b60ff8411156190f8576190f8618f7b565b50506001821b61128a565b5060208310610133831016604e8410600b8410161715619126575081810a61128a565b6191336000198484619068565b806000190482111561914757619147618f7b565b029392505050565b6000610f5f83836190ab565b808202811582820484141761128a5761128a618f7b565b60208082526033908201527f45746e795374616b696e673a204f6e6c7920612063616e63656c656420636f6e60408201527274726163742063616e20626520656e6465642160681b606082015260800190565b6020808252603d908201527f45746e795374616b696e673a2054686520636f6e74726163742063616e20626560408201527f207465726d696e6174656420616674657220697420657870697265732e000000606082015260800190565b60208082526030908201527f45746e795374616b696e673a205265776172642061646472657373206973207460408201526f6865207a65726f20616464726573732160801b606082015260800190565b8082018082111561128a5761128a618f7b565b6020808252605c908201526000805160206194f783398151915260408201527f6573732063616e207465726d696e61746520612042617365205374616b65204360608201527f6f6e747261637420616e64206170706c792070656e616c746965732100000000608082015260a00190565b60208082526064908201527f45746e795374616b696e673a20536f6d657468696e672077656e742077726f6e60408201527f672e205468652045746865726e69747920436c6f756420536d617274436f6e7460608201527f726163742061646472657373206973206e6f7420636f72726563746c792073656080820152637475702160e01b60a082015260c00190565b60208082526035908201527f45746e795374616b696e673a204e6f646520616c72656164792068617320616e604082015274206578697374696e672062617365207374616b652160581b606082015260800190565b60208082526022908201527f45746e795374616b696e673a204e6f6465206861732045544e5920746f6b656e604082015261732160f01b606082015260800190565b6020808252603e9082015260008051602061953783398151915260408201527f62616c616e636520617661696c61626c6520666f72207374616b696e67210000606082015260800190565b60208082526046908201527f45746e795374616b696e673a20546865206e6f6465206164647265737320736860408201527f6f756c6420626520646966666572656e74207468616e2072657761726420616460608201526564726573732160d01b608082015260a00190565b6000826194f157634e487b7160e01b600052601260045260246000fd5b50049056fe45746e795374616b696e673a204f6e6c79206120636f6d70616e792061646472ee821fc4af1ea42a6c6174adb5fd292ad9e326c120629b92006d036545c3c66b45746e795374616b696e673a2054686520616d6f756e74206578636565647320a2646970667358221220d86e6e6f8fa2602a52df3e5b9fd1ef7f79783917d841e44134aa8a5a6c94a9ae64736f6c634300081a0033