Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- ConnectivityTrackerHbbft
- Optimization enabled
- true
- Compiler version
- v0.8.25+commit.b61c2a91
- Optimization runs
- 800
- Verified at
- 2024-12-09 15:41:04.141638Z
contracts/ConnectivityTrackerHbbft.sol
// SPDX-License-Identifier: Apache 2.0pragma solidity =0.8.25;import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";import { IConnectivityTrackerHbbft } from "./interfaces/IConnectivityTrackerHbbft.sol";import { IValidatorSetHbbft } from "./interfaces/IValidatorSetHbbft.sol";import { IStakingHbbft } from "./interfaces/IStakingHbbft.sol";import { IBlockRewardHbbft } from "./interfaces/IBlockRewardHbbft.sol";import { IBonusScoreSystem } from "./interfaces/IBonusScoreSystem.sol";import { Unauthorized, ZeroAddress } from "./lib/Errors.sol";import { ValueGuards } from "./lib/ValueGuards.sol";contract ConnectivityTrackerHbbft is Initializable, OwnableUpgradeable, IConnectivityTrackerHbbft, ValueGuards { using EnumerableSet for EnumerableSet.AddressSet; /** * @dev The address of the {ValidatorSetHbbft} contract. */ IValidatorSetHbbft public validatorSetContract; /** * @dev The address of the {StakingHbbft} contract. */ IStakingHbbft public stakingContract; /** * @dev The address of the {BlockRewardHbbft} contract. */ IBlockRewardHbbft public blockRewardContract; /** * @dev Time since the beginning of the epoch during which reports are not accepted. * @custom:oz-renamed-from minReportAgeBlocks */ uint256 public reportDisallowPeriod; /** * @dev Parameter that binds Hbbft Fault tolerance with */ uint256 public earlyEpochEndToleranceLevel; /** * @dev Early epoch end historical data. */ mapping(uint256 => bool) public isEarlyEpochEnd; /** * @dev Mapping the epoch number to the list of validators that have disconnected in it. */ mapping(uint256 => EnumerableSet.AddressSet) private _flaggedValidators; /** * @dev Mapping of reported validators and their reporters by epoch number. */ mapping(uint256 => mapping(address => EnumerableSet.AddressSet)) private _reporters; /** * @dev Indicats wheter validators were penalised for bad performance in specific epoch. */ mapping(uint256 => bool) private _epochPenaltiesSent; /** * @dev The address of the {BonusScoreSystem} contract. */ IBonusScoreSystem public bonusScoreContract; /** * @dev Timestamp when the validator was marked as faulty in a specific epoch. */ mapping(uint256 => mapping(address => uint256)) private _disconnectTimestamp; /** * @dev Emitted by the {setReportDisallowPeriod} function. * @param _reportDisallowPeriodSeconds New report disallow period value in seconds. */ event SetReportDisallowPeriod(uint256 _reportDisallowPeriodSeconds); /** * @dev Emitted when `validator` was reported by `reporter` for lost connection at block `blockNumber`. * @param reporter Reporting validator address. * @param validator Address of the validator with which the connection was lost. * @param blockNumber Block number when connection was lost. */ event ReportMissingConnectivity(address indexed reporter, address indexed validator, uint256 indexed blockNumber); /** * @dev Emitted when `validator` was reported by `reporter` as reconnected at block `blockNumber`. * @param reporter Reporting validator address. * @param validator Address of the reconnected validator. * @param blockNumber Block number when reported validator reconnected. */ event ReportReconnect(address indexed reporter, address indexed validator, uint256 indexed blockNumber); /** * @dev Emitted to signal that the count of disconnected validators exceeded * the threshold and current epoch `epoch` will end earlier. * @param epoch Staking epoch number. * @param blockNumber Block number in which the decision was made. */ event NotifyEarlyEpochEnd(uint256 indexed epoch, uint256 indexed blockNumber); error AlreadyReported(address reporter, address validator); error CannotReportByFlaggedValidator(address reporter); error InvalidBlock(); error OnlyValidator(); error ReportTooEarly(); error UnknownReconnectReporter(address reporter, address validator); error EpochPenaltiesAlreadySent(uint256 epoch); /** * @custom:oz-upgrades-unsafe-allow constructor */ constructor() { // Prevents initialization of implementation contract _disableInitializers(); } /** * @dev Check that the caller is {BlockRewardHbbft} contract. * * Reverts with an {Unauthorized} error. */ modifier onlyBlockRewardContract() { if (msg.sender != address(blockRewardContract)) { revert Unauthorized(); } _; } function initialize( address _contractOwner, address _validatorSetContract, address _stakingContract, address _blockRewardContract, address _bonusScoreContract, uint256 _reportDisallowPeriodSeconds ) external initializer { if ( _contractOwner == address(0) || _validatorSetContract == address(0) || _stakingContract == address(0) || _blockRewardContract == address(0) || _bonusScoreContract == address(0) ) { revert ZeroAddress(); } __Ownable_init(_contractOwner); validatorSetContract = IValidatorSetHbbft(_validatorSetContract); stakingContract = IStakingHbbft(_stakingContract); blockRewardContract = IBlockRewardHbbft(_blockRewardContract); bonusScoreContract = IBonusScoreSystem(_bonusScoreContract); reportDisallowPeriod = _reportDisallowPeriodSeconds; earlyEpochEndToleranceLevel = 2; uint256 step = 3 minutes; uint256[] memory reportDisallowPeriodAllowedParams = new uint256[](10); for (uint256 i = 0; i < 10; i++) { reportDisallowPeriodAllowedParams[i] = step + (i * step); } __initAllowedChangeableParameter( this.setReportDisallowPeriod.selector, this.reportDisallowPeriod.selector, reportDisallowPeriodAllowedParams ); } /** * @dev This function sets the period of time during which reports are not accepted. * Can only be called by contract owner. * @param _reportDisallowPeriodSeconds Time period in seconds. * * Emits a {SetReportDisallowPeriod} event. */ function setReportDisallowPeriod(uint256 _reportDisallowPeriodSeconds) external onlyOwner withinAllowedRange(_reportDisallowPeriodSeconds) { reportDisallowPeriod = _reportDisallowPeriodSeconds; emit SetReportDisallowPeriod(_reportDisallowPeriodSeconds); } /** * @dev Report that the connection to the specified validator was lost at block `blockNumber`. * Callable only by active validators. * * @param validator Validator address with which the connection was lost. * @param blockNumber Block number where the connection was lost. * @param blockHash Hash of this block. * * Emits a {ReportMissingConnectivity} event. */ function reportMissingConnectivity(address validator, uint256 blockNumber, bytes32 blockHash) external { checkReportMissingConnectivityCallable(msg.sender, validator, blockNumber, blockHash); uint256 epoch = currentEpoch(); uint256 currentScore = getValidatorConnectivityScore(epoch, validator); if (currentScore == 0) { // slither-disable-next-line unused-return _flaggedValidators[epoch].add(validator); } // slither-disable-next-line unused-return _reporters[epoch][validator].add(msg.sender); if (isFaultyValidator(epoch, validator)) { _markValidatorFaulty(epoch, validator); } _decideEarlyEpochEndNeeded(epoch); emit ReportMissingConnectivity(msg.sender, validator, blockNumber); } /** * @dev Report that the connection to the specified validator was restored at block `blockNumber`. * Callable only by active validators. * * @param validator Validator address with which the connection was restored. * @param blockNumber Block number where the connection was restored. * @param blockHash Hash of this block. * * Emits a {ReportReconnect} event. */ function reportReconnect(address validator, uint256 blockNumber, bytes32 blockHash) external { checkReportReconnectCallable(msg.sender, validator, blockNumber, blockHash); uint256 epoch = currentEpoch(); uint256 currentScore = getValidatorConnectivityScore(epoch, validator); // slither-disable-next-line unused-return _reporters[epoch][validator].remove(msg.sender); if (currentScore == 1) { // slither-disable-next-line unused-return _flaggedValidators[epoch].remove(validator); // All reporters confirmed that this validator reconnected, // decrease validator bonus score for bad performance based on disconnect time interval. uint256 disconnectTimestamp = _disconnectTimestamp[epoch][validator]; if (disconnectTimestamp != 0) { uint256 disconnectPeriod = block.timestamp - disconnectTimestamp; bonusScoreContract.penaliseBadPerformance(validator, disconnectPeriod); delete _disconnectTimestamp[epoch][validator]; } } _decideEarlyEpochEndNeeded(epoch); emit ReportReconnect(msg.sender, validator, blockNumber); } /** * @dev Send bad performance bonus score penalties to validators * that have not yet reconnected at the end of the epoch. * Can only be called by {BlockRewardHbbft} contract. * * @param epoch Staking epoch number. * * Reverts with {EpochPenaltiesAlreadySent} if penalties for specified `epoch` already sent. */ function penaliseFaultyValidators(uint256 epoch) external onlyBlockRewardContract { if (_epochPenaltiesSent[epoch]) { revert EpochPenaltiesAlreadySent(epoch); } _epochPenaltiesSent[epoch] = true; address[] memory flaggedValidators = getFlaggedValidatorsByEpoch(epoch); for (uint256 i = 0; i < flaggedValidators.length; ++i) { if (!isFaultyValidator(epoch, flaggedValidators[i])) { continue; } bonusScoreContract.penaliseBadPerformance(flaggedValidators[i], 0); } } /** * @dev Returns true if the validator `validator` was reported * by the specified `reporter`at the current epoch. * @param validator Valdiator address. * @param reporter Reporting validator address. */ function isReported(uint256, address validator, address reporter) external view returns (bool) { return _reporters[currentEpoch()][validator].contains(reporter); } function getValidatorConnectivityScore(uint256 epoch, address validator) public view returns (uint256) { return _reporters[epoch][validator].length(); } /** * @dev Returns true if the validator `validator` was marked as faulty * (majority of other validators reported missing connectivity) in the specified `epoch`. * @param epoch Staking epoch number. * @param validator Validator address */ function isFaultyValidator(uint256 epoch, address validator) public view returns (bool) { return getValidatorConnectivityScore(epoch, validator) >= _getReportersThreshold(epoch); } function checkReportMissingConnectivityCallable( address caller, address validator, uint256 blockNumber, bytes32 blockHash ) public view { uint256 epoch = currentEpoch(); _validateParams(epoch, caller, blockNumber, blockHash); if (_reporters[epoch][validator].contains(caller)) { revert AlreadyReported(caller, validator); } } function checkReportReconnectCallable( address caller, address validator, uint256 blockNumber, bytes32 blockHash ) public view { uint256 epoch = currentEpoch(); _validateParams(epoch, caller, blockNumber, blockHash); // Only "missing connectivity" reporter can also report reconnect if (!_reporters[epoch][validator].contains(caller)) { revert UnknownReconnectReporter(caller, validator); } } /** * @dev Get list of validators flagged for missing connectivity in the specified `epoch`. * @param epoch Staking epoch number. */ function getFlaggedValidatorsByEpoch(uint256 epoch) public view returns (address[] memory) { return _flaggedValidators[epoch].values(); } /** * @dev Get list of validators flagged for missing connectivity in the current epoch. * See {getFlaggedValidatorsByEpoch}. */ function getFlaggedValidators() public view returns (address[] memory) { return getFlaggedValidatorsByEpoch(currentEpoch()); } /** * @dev Get list of validators flagged for missing connectivity in the specified staking epoch `epoch`. * @param epoch Staking epoch number. */ function getFlaggedValidatorsCount(uint256 epoch) public view returns (uint256) { return _flaggedValidators[epoch].length(); } /** * @dev Get current staking epoch number. * See {StakingHbbft-stakingEpoch} */ function currentEpoch() public view returns (uint256) { return IStakingHbbft(stakingContract).stakingEpoch(); } /** * @dev Returns the number of validators that, if exceeded, * will trigger an early end of the current staking epoch. */ function earlyEpochEndThreshold() public view returns (uint256) { uint256 networkSize = IValidatorSetHbbft(validatorSetContract).getCurrentValidatorsCount(); uint256 hbbftFaultTolerance = networkSize / 3; if (hbbftFaultTolerance <= earlyEpochEndToleranceLevel) { return 0; } else { return hbbftFaultTolerance - earlyEpochEndToleranceLevel; } } /** * @dev Returns faulty validators count in given epoch `epoch`. * @param epoch Staking epoch number. */ function countFaultyValidators(uint256 epoch) public view returns (uint256) { return _countFaultyValidators(epoch); } function _decideEarlyEpochEndNeeded(uint256 epoch) private { // skip checks since notification has already been sent if (isEarlyEpochEnd[epoch]) { return; } uint256 threshold = earlyEpochEndThreshold(); uint256 faultyValidatorsCount = _countFaultyValidators(epoch); // threshold has not been passed if (faultyValidatorsCount < threshold) { return; } isEarlyEpochEnd[epoch] = true; blockRewardContract.notifyEarlyEpochEnd(); emit NotifyEarlyEpochEnd(epoch, block.number); } function _markValidatorFaulty(uint256 epoch, address validator) private { if (_disconnectTimestamp[epoch][validator] != 0) { // validator already marked as faulty return; } _disconnectTimestamp[epoch][validator] = block.timestamp; validatorSetContract.notifyUnavailability(validator); } function _getReportersThreshold(uint256 epoch) private view returns (uint256) { uint256 unflaggedValidatorsCount = validatorSetContract.getCurrentValidatorsCount() - getFlaggedValidatorsCount(epoch); return (2 * unflaggedValidatorsCount) / 3 + 1; } function _countFaultyValidators(uint256 epoch) private view returns (uint256) { uint256 reportersThreshold = _getReportersThreshold(epoch); uint256 result = 0; address[] memory flaggedValidators = getFlaggedValidatorsByEpoch(epoch); for (uint256 i = 0; i < flaggedValidators.length; ++i) { address validator = flaggedValidators[i]; if (getValidatorConnectivityScore(epoch, validator) >= reportersThreshold) { ++result; } } return result; } function _validateParams(uint256 epoch, address caller, uint256 blockNumber, bytes32 blockHash) private view { if (!validatorSetContract.isValidator(caller)) { revert OnlyValidator(); } if (blockNumber > block.number || blockhash(blockNumber) != blockHash) { revert InvalidBlock(); } if (_flaggedValidators[epoch].contains(caller)) { revert CannotReportByFlaggedValidator(caller); } uint256 epochStartTimestamp = stakingContract.stakingEpochStartTime(); if (block.timestamp < epochStartTimestamp + reportDisallowPeriod) { revert ReportTooEarly(); } }}
@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)pragma solidity ^0.8.20;import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";import {Initializable} from "../proxy/utils/Initializable.sol";/** * @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. * * The initial owner is set to the address provided by the deployer. 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. */abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(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 { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); }}
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)pragma solidity ^0.8.20;/** * @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 proxied contracts do not make use of 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. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * 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 {ERC1967Proxy-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. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } }}
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)pragma solidity ^0.8.20;import {Initializable} from "../proxy/utils/Initializable.sol";/** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; }}
@openzeppelin/contracts/utils/structs/EnumerableSet.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.pragma solidity ^0.8.20;/** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; }}
contracts/interfaces/IBlockRewardHbbft.sol
// SPDX-License-Identifier: Apache 2.0pragma solidity =0.8.25;interface IBlockRewardHbbft { function addToReinsertPot() external payable; function notifyEarlyEpochEnd() external; function getGovernanceAddress() external view returns (address);}
contracts/interfaces/IBonusScoreSystem.sol
// SPDX-License-Identifier: Apache 2.0pragma solidity =0.8.25;enum ScoringFactor { StandByBonus, NoStandByPenalty, NoKeyWritePenalty, BadPerformancePenalty}interface IBonusScoreSystem { function getValidatorScore(address mining) external view returns (uint256); function rewardStandBy(address mining, uint256 time) external; function penaliseNoStandBy(address mining, uint256 time) external; function penaliseNoKeyWrite(address mining) external; function penaliseBadPerformance(address mining, uint256 time) external;}
contracts/interfaces/IConnectivityTrackerHbbft.sol
// SPDX-License-Identifier: Apache 2.0pragma solidity =0.8.25;interface IConnectivityTrackerHbbft { function reportMissingConnectivity( address validator, uint256 blockNum, bytes32 blockHash ) external; function reportReconnect( address validator, uint256 blockNumber, bytes32 blockHash ) external; function checkReportMissingConnectivityCallable( address caller, address validator, uint256 blockNumber, bytes32 blockHash ) external view; function checkReportReconnectCallable( address caller, address validator, uint256 blockNumber, bytes32 blockHash ) external view; function isEarlyEpochEnd(uint256 epoch) external view returns (bool); function penaliseFaultyValidators(uint256 epoch) external;}
contracts/interfaces/IStakingHbbft.sol
// SPDX-License-Identifier: Apache 2.0pragma solidity =0.8.25;interface IStakingHbbft { struct PoolRewardShares { uint256 validatorShare; uint256 nodeOperatorShare; uint256 delegatorsShare; } struct StakingParams { address _validatorSetContract; address _bonusScoreContract; address[] _initialStakingAddresses; uint256 _delegatorMinStake; uint256 _candidateMinStake; uint256 _maxStake; uint256 _stakingFixedEpochDuration; uint256 _stakingTransitionTimeframeLength; uint256 _stakingWithdrawDisallowPeriod; } function incrementStakingEpoch() external; function removePool(address) external; function removePools() external; function setStakingEpochStartTime(uint256) external; function notifyKeyGenFailed() external; function notifyAvailability(address _stakingAddress) external; function notifyNetworkOfftimeDetected(uint256) external; function updatePoolLikelihood(address mining, uint256 validatorScore) external; function getPoolPublicKey(address _poolAddress) external view returns (bytes memory); function getPoolsLikelihood() external view returns (uint256[] memory, uint256); function getPoolsToBeElected() external view returns (address[] memory); function getPoolsToBeRemoved() external view returns (address[] memory); function getPoolsInactive() external view returns (address[] memory); function isPoolActive(address) external view returns (bool); function isPoolValid(address) external view returns (bool); function MAX_CANDIDATES() external pure returns (uint256); // solhint-disable-line func-name-mixedcase function orderedWithdrawAmount(address, address) external view returns (uint256); function poolDelegators(address) external view returns (address[] memory); function setValidatorInternetAddress( address, bytes16, bytes2 ) external; function stakeAmount(address, address) external view returns (uint256); function stakeAmountTotal(address) external view returns (uint256); function totalStakedAmount() external view returns (uint256); function stakingWithdrawDisallowPeriod() external view returns (uint256); function stakingEpoch() external view returns (uint256); function stakingFixedEpochDuration() external view returns (uint256); function startTimeOfNextPhaseTransition() external view returns (uint256); function stakingFixedEpochEndTime() external view returns (uint256); function stakingEpochStartTime() external view returns (uint256); function stakingEpochStartBlock() external view returns (uint256); function restake( address _poolStakingAddress, uint256 validatorReward ) external payable; function snapshotPoolStakeAmounts( uint256 _epoch, address _stakingPool ) external; function getPoolValidatorStakeAmount( uint256 _epoch, address _stakingPool ) external view returns (uint256);}
contracts/interfaces/IValidatorSetHbbft.sol
// SPDX-License-Identifier: Apache 2.0pragma solidity =0.8.25;interface IValidatorSetHbbft { struct ValidatorSetParams { address blockRewardContract; address randomContract; address stakingContract; address keyGenHistoryContract; address bonusScoreContract; address connectivityTrackerContract; uint256 validatorInactivityThreshold; } // Key Generation states of validator. enum KeyGenMode { NotAPendingValidator, WritePart, WaitForOtherParts, WriteAck, WaitForOtherAcks, AllKeysDone } function announceAvailability(uint256, bytes32) external; function finalizeChange() external; function newValidatorSet() external; function setStakingAddress(address, address) external; function handleFailedKeyGeneration() external; function isFullHealth() external view returns (bool); function blockRewardContract() external view returns (address); function canCallAnnounceAvailability(address _miningAddress) external view returns (bool); function getPendingValidators() external view returns (address[] memory); function getPreviousValidators() external view returns (address[] memory); function getValidators() external view returns (address[] memory); function isValidator(address) external view returns (bool); function isValidatorOrPending(address) external view returns (bool); function isPendingValidator(address) external view returns (bool); function getPendingValidatorKeyGenerationMode(address) external view returns (KeyGenMode); function maxValidators() external view returns (uint256); function miningByStakingAddress(address) external view returns (address); function randomContract() external view returns (address); function notifyUnavailability(address) external; function stakingByMiningAddress(address) external view returns (address); function publicKeyByStakingAddress(address) external view returns (bytes memory); function getPublicKey(address) external view returns (bytes memory); function getStakingContract() external view returns (address); function validatorAvailableSince(address) external view returns (uint256); function isValidatorAbandoned(address) external view returns (bool); function getValidatorCountSweetSpot(uint256) external view returns (uint256); function getCurrentValidatorsCount() external view returns (uint256);}
contracts/lib/Errors.sol
// SPDX-License-Identifier: Apache 2.0pragma solidity =0.8.25;error Unauthorized();error ValidatorsListEmpty();error ZeroAddress();error ZeroGasPrice();
contracts/lib/ValueGuards.sol
// SPDX-License-Identifier: Apache 2.0pragma solidity =0.8.25;import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";abstract contract ValueGuards is OwnableUpgradeable { // =============================================== Storage ======================================================== /** * @dev Represents a parameter range for a specific getter function. * @param getter The getter function signature. * @param range The range of values for the parameter. */ struct ParameterRange { bytes4 getter; uint256[] range; } struct ValueGuardsStorage { /** * @dev A mapping that stores the allowed parameter ranges for each function signature. */ mapping(bytes4 => ParameterRange) allowedParameterRange; } bytes32 private constant VALUEGUARDS_STORAGE_NAMESPACE = keccak256(abi.encode(uint256(keccak256("valueguards.storage")) - 1)) & ~bytes32(uint256(0xff)); function _getValueGuardsStorage() private pure returns (ValueGuardsStorage storage $) { bytes32 slot = VALUEGUARDS_STORAGE_NAMESPACE; // solhint-disable-next-line no-inline-assembly assembly { $.slot := slot } } // ============================================== Events ========================================================== /** * @dev Event emitted when changeable parameters are set. * @param setter Setter function signature. * @param getter Getter function signature. * @param params An array of uint256 values representing the parameters. */ event SetChangeableParameter(bytes4 setter, bytes4 getter, uint256[] params); /** * @dev Emitted when changeable parameters are removed. * @param funcSelector The function selector of the removed changeable parameters. */ event RemoveChangeableParameter(bytes4 funcSelector); // ============================================== Errors ========================================================== error NewValueOutOfRange(uint256 _newVal); error GetterCallFailed(); // ============================================== Modifiers ======================================================= /** * @dev Modifier to check if a new value is within the allowed range. * @param newVal The new value to be checked. * @notice This modifier is used to ensure that the new value is within the allowed range. * If the new value is not within the allowed range, the function using this modifier * will revert with an error message. */ modifier withinAllowedRange(uint256 newVal) { if (!isWithinAllowedRange(msg.sig, newVal)) { revert NewValueOutOfRange(newVal); } _; } // =============================================== Initializers ==================================================== /** * @dev Inits the allowed changeable parameter for a specific setter function. * @param setter Setter function selector. * @param getter Getter function selector. * @param params The array of allowed parameter values. */ function __initAllowedChangeableParameter( bytes4 setter, bytes4 getter, uint256[] memory params ) internal onlyInitializing { ValueGuardsStorage storage $ = _getValueGuardsStorage(); $.allowedParameterRange[setter] = ParameterRange({ getter: getter, range: params }); emit SetChangeableParameter(setter, getter, params); } // =============================================== Setters ======================================================== /** * @dev Sets the allowed changeable parameter for a specific setter function. * @param setter Setter function selector. * @param getter Getter function selector. * @param params The array of allowed parameter values. */ function setAllowedChangeableParameter(bytes4 setter, bytes4 getter, uint256[] calldata params) public onlyOwner { ValueGuardsStorage storage $ = _getValueGuardsStorage(); $.allowedParameterRange[setter] = ParameterRange({ getter: getter, range: params }); emit SetChangeableParameter(setter, getter, params); } /** * @dev Removes the allowed changeable parameter for a given function selector. * @param funcSelector The function selector for which the allowed changeable parameter should be removed. */ function removeAllowedChangeableParameter(bytes4 funcSelector) public onlyOwner { ValueGuardsStorage storage $ = _getValueGuardsStorage(); delete $.allowedParameterRange[funcSelector]; emit RemoveChangeableParameter(funcSelector); } // =============================================== Getters ======================================================== /** * @dev Checks if the given `newVal` is within the allowed range for the specified function selector. * @param funcSelector The function selector. * @param newVal The new value to be checked. * @return A boolean indicating whether the `newVal` is within the allowed range. */ function isWithinAllowedRange(bytes4 funcSelector, uint256 newVal) public view returns (bool) { ValueGuardsStorage storage $ = _getValueGuardsStorage(); ParameterRange memory allowedRange = $.allowedParameterRange[funcSelector]; if (allowedRange.range.length == 0) { return false; } uint256[] memory range = allowedRange.range; uint256 currVal = _getValueWithSelector(allowedRange.getter); for (uint256 i = 0; i < range.length; i++) { if (range[i] == currVal) { uint256 leftVal = (i > 0) ? range[i - 1] : range[0]; uint256 rightVal = (i < range.length - 1) ? range[i + 1] : range[range.length - 1]; return !(newVal != leftVal && newVal != rightVal); } } return false; } function getAllowedParamsRange(string memory _selector) external view returns (ParameterRange memory) { return _getValueGuardsStorage().allowedParameterRange[bytes4(keccak256(bytes(_selector)))]; } function getAllowedParamsRangeWithSelector(bytes4 _selector) external view returns (ParameterRange memory) { return _getValueGuardsStorage().allowedParameterRange[_selector]; } // =============================================== Internal ======================================================== /** * @dev Internal function to get the value of a contract state variable using a getter function. * @param getterSelector The selector of the getter function. * @return The value of the contract state variable. */ function _getValueWithSelector(bytes4 getterSelector) private view returns (uint256) { bytes memory payload = abi.encodeWithSelector(getterSelector); (bool success, bytes memory result) = address(this).staticcall(payload); if (!success) { revert GetterCallFailed(); } return abi.decode(result, (uint256)); }}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"error","name":"AlreadyReported","inputs":[{"type":"address","name":"reporter","internalType":"address"},{"type":"address","name":"validator","internalType":"address"}]},{"type":"error","name":"CannotReportByFlaggedValidator","inputs":[{"type":"address","name":"reporter","internalType":"address"}]},{"type":"error","name":"EpochPenaltiesAlreadySent","inputs":[{"type":"uint256","name":"epoch","internalType":"uint256"}]},{"type":"error","name":"GetterCallFailed","inputs":[]},{"type":"error","name":"InvalidBlock","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"NewValueOutOfRange","inputs":[{"type":"uint256","name":"_newVal","internalType":"uint256"}]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"OnlyValidator","inputs":[]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"error","name":"ReportTooEarly","inputs":[]},{"type":"error","name":"Unauthorized","inputs":[]},{"type":"error","name":"UnknownReconnectReporter","inputs":[{"type":"address","name":"reporter","internalType":"address"},{"type":"address","name":"validator","internalType":"address"}]},{"type":"error","name":"ZeroAddress","inputs":[]},{"type":"event","name":"Initialized","inputs":[{"type":"uint64","name":"version","internalType":"uint64","indexed":false}],"anonymous":false},{"type":"event","name":"NotifyEarlyEpochEnd","inputs":[{"type":"uint256","name":"epoch","internalType":"uint256","indexed":true},{"type":"uint256","name":"blockNumber","internalType":"uint256","indexed":true}],"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":"RemoveChangeableParameter","inputs":[{"type":"bytes4","name":"funcSelector","internalType":"bytes4","indexed":false}],"anonymous":false},{"type":"event","name":"ReportMissingConnectivity","inputs":[{"type":"address","name":"reporter","internalType":"address","indexed":true},{"type":"address","name":"validator","internalType":"address","indexed":true},{"type":"uint256","name":"blockNumber","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"ReportReconnect","inputs":[{"type":"address","name":"reporter","internalType":"address","indexed":true},{"type":"address","name":"validator","internalType":"address","indexed":true},{"type":"uint256","name":"blockNumber","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"SetChangeableParameter","inputs":[{"type":"bytes4","name":"setter","internalType":"bytes4","indexed":false},{"type":"bytes4","name":"getter","internalType":"bytes4","indexed":false},{"type":"uint256[]","name":"params","internalType":"uint256[]","indexed":false}],"anonymous":false},{"type":"event","name":"SetReportDisallowPeriod","inputs":[{"type":"uint256","name":"_reportDisallowPeriodSeconds","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IBlockRewardHbbft"}],"name":"blockRewardContract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IBonusScoreSystem"}],"name":"bonusScoreContract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[],"name":"checkReportMissingConnectivityCallable","inputs":[{"type":"address","name":"caller","internalType":"address"},{"type":"address","name":"validator","internalType":"address"},{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"bytes32","name":"blockHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[],"name":"checkReportReconnectCallable","inputs":[{"type":"address","name":"caller","internalType":"address"},{"type":"address","name":"validator","internalType":"address"},{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"bytes32","name":"blockHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"countFaultyValidators","inputs":[{"type":"uint256","name":"epoch","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"currentEpoch","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"earlyEpochEndThreshold","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"earlyEpochEndToleranceLevel","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct ValueGuards.ParameterRange","components":[{"type":"bytes4","name":"getter","internalType":"bytes4"},{"type":"uint256[]","name":"range","internalType":"uint256[]"}]}],"name":"getAllowedParamsRange","inputs":[{"type":"string","name":"_selector","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct ValueGuards.ParameterRange","components":[{"type":"bytes4","name":"getter","internalType":"bytes4"},{"type":"uint256[]","name":"range","internalType":"uint256[]"}]}],"name":"getAllowedParamsRangeWithSelector","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getFlaggedValidators","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getFlaggedValidatorsByEpoch","inputs":[{"type":"uint256","name":"epoch","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getFlaggedValidatorsCount","inputs":[{"type":"uint256","name":"epoch","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getValidatorConnectivityScore","inputs":[{"type":"uint256","name":"epoch","internalType":"uint256"},{"type":"address","name":"validator","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"_contractOwner","internalType":"address"},{"type":"address","name":"_validatorSetContract","internalType":"address"},{"type":"address","name":"_stakingContract","internalType":"address"},{"type":"address","name":"_blockRewardContract","internalType":"address"},{"type":"address","name":"_bonusScoreContract","internalType":"address"},{"type":"uint256","name":"_reportDisallowPeriodSeconds","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isEarlyEpochEnd","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isFaultyValidator","inputs":[{"type":"uint256","name":"epoch","internalType":"uint256"},{"type":"address","name":"validator","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isReported","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"validator","internalType":"address"},{"type":"address","name":"reporter","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isWithinAllowedRange","inputs":[{"type":"bytes4","name":"funcSelector","internalType":"bytes4"},{"type":"uint256","name":"newVal","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"penaliseFaultyValidators","inputs":[{"type":"uint256","name":"epoch","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeAllowedChangeableParameter","inputs":[{"type":"bytes4","name":"funcSelector","internalType":"bytes4"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"reportDisallowPeriod","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"reportMissingConnectivity","inputs":[{"type":"address","name":"validator","internalType":"address"},{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"bytes32","name":"blockHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"reportReconnect","inputs":[{"type":"address","name":"validator","internalType":"address"},{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"bytes32","name":"blockHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAllowedChangeableParameter","inputs":[{"type":"bytes4","name":"setter","internalType":"bytes4"},{"type":"bytes4","name":"getter","internalType":"bytes4"},{"type":"uint256[]","name":"params","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setReportDisallowPeriod","inputs":[{"type":"uint256","name":"_reportDisallowPeriodSeconds","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IStakingHbbft"}],"name":"stakingContract","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IValidatorSetHbbft"}],"name":"validatorSetContract","inputs":[]}]
Deployed ByteCode
0x6080604052348015600f57600080fd5b506016601a565b60ca565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560695760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c75780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b61233a806100d96000396000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806395b6ef0c1161010f578063c2428693116100a2578063ee99205c11610071578063ee99205c14610439578063f2fde38b1461044c578063f4064e171461045f578063fb58b40e1461047257600080fd5b8063c2428693146103eb578063dfc8bf4e146103fe578063e2ed033014610411578063e6de3f031461042657600080fd5b8063b710c15d116100de578063b710c15d14610392578063ba08d237146103b2578063bed8968c146103c5578063bf348f86146103d857600080fd5b806395b6ef0c14610351578063a57c615314610364578063b280c0941461036c578063b2a684211461037f57600080fd5b80634346845f11610187578063766718081161015657806376671808146102f35780637d8149db146102fb5780638da5cb5b1461030e578063911cee741461033e57600080fd5b80634346845f146102b257806348bf1aa6146102c557806356b54bae146102d8578063715018a6146102eb57600080fd5b80631041215e116101c35780631041215e14610262578063116f114914610279578063161b07b21461028c57806329cf85641461029f57600080fd5b8063060b2849146101ea5780630b770cdf146101ff5780630be021091461022f575b600080fd5b6101fd6101f8366004611d2e565b61047b565b005b600954610212906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61025261023d366004611d70565b60056020526000908152604090205460ff1681565b6040519015158152602001610226565b61026b60045481565b604051908152602001610226565b6101fd610287366004611d70565b6104fc565b61025261029a366004611d89565b610578565b61026b6102ad366004611d89565b610598565b6101fd6102c0366004611dcd565b6105ca565b6101fd6102d3366004611d70565b6106d0565b600254610212906001600160a01b031681565b6101fd610829565b61026b61083d565b6101fd610309366004611e5e565b6108b0565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316610212565b6101fd61034c366004611e79565b610932565b6101fd61035f366004611eac565b610a08565b61026b610c88565b61026b61037a366004611d70565b610d2d565b6101fd61038d366004611e79565b610d38565b6103a56103a0366004611f2f565b610eb9565b6040516102269190611fe0565b6102526103c0366004612042565b610f69565b6101fd6103d3366004611d2e565b611144565b6103a56103e6366004611e5e565b6111b8565b6102526103f936600461206c565b61125d565b600054610212906001600160a01b031681565b6104196112a3565b60405161022691906120a8565b61026b610434366004611d70565b6112b0565b600154610212906001600160a01b031681565b6101fd61045a3660046120f5565b6112c7565b61041961046d366004611d70565b611305565b61026b60035481565b600061048561083d565b90506104938186858561131f565b60008181526007602090815260408083206001600160a01b038816845290915290206104bf90866114b6565b156104f557604051632c91ad2b60e11b81526001600160a01b038087166004830152851660248201526044015b60405180910390fd5b5050505050565b6105046114d8565b8061051b6000356001600160e01b03191682610f69565b61053b576040516373330d9b60e01b8152600481018290526024016104ec565b60038290556040518281527ff0ae05d1ef296238e04486dbfa703343cb8a565a7926535e21eebd26211d5154906020015b60405180910390a15050565b600061058383611533565b61058d8484610598565b101590505b92915050565b60008281526007602090815260408083206001600160a01b038516845290915281206105c3906115e2565b9392505050565b6105d26114d8565b60006105dc6115ec565b90506040518060400160405280857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200184848080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509390945250506001600160e01b031988168152602084815260409091208351815463ffffffff191660e09190911c178155838201518051919350610688926001850192910190611c98565b509050507f3665bf9cd0ba4ddceeec259e21dcf8a4510f3b1130bd42e950828e69d85408ba858585856040516106c19493929190612110565b60405180910390a15050505050565b6002546001600160a01b031633146106fa576040516282b42960e81b815260040160405180910390fd5b60008181526008602052604090205460ff161561072d5760405163e711188160e01b8152600481018290526024016104ec565b6000818152600860205260408120805460ff1916600117905561074f82611305565b905060005b815181101561082457610780838383815181106107735761077361217d565b6020026020010151610578565b1561081c5760095482516001600160a01b0390911690633dc12d23908490849081106107ae576107ae61217d565b602002602001015160006040518363ffffffff1660e01b81526004016107e99291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b15801561080357600080fd5b505af1158015610817573d6000803e3d6000fd5b505050505b600101610754565b505050565b6108316114d8565b61083b600061164e565b565b60015460408051630f29818d60e31b815290516000926001600160a01b03169163794c0c689160048083019260209291908290030181865afa158015610887573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ab9190612193565b905090565b6108b86114d8565b60006108c26115ec565b6001600160e01b031983166000908152602082905260408120805463ffffffff191681559192506108f66001830182611ce3565b50506040516001600160e01b0319831681527fed27cb02231782dadf13473a7828cb980c4d685791b7a3136dde00f8c3594cb69060200161056c565b61093e3384848461047b565b600061094861083d565b905060006109568286610598565b90508060000361097a57600082815260066020526040902061097890866116cc565b505b60008281526007602090815260408083206001600160a01b038916845290915290206109a690336116cc565b506109b18286610578565b156109c0576109c082866116e1565b6109c98261178d565b60405184906001600160a01b0387169033907fe84fbfa7fbefb93358b3d7d314bc48b17f721c435443246047f93bbc7b8d0eef90600090a45050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610a535750825b905060008267ffffffffffffffff166001148015610a705750303b155b905081158015610a7e575080155b15610a9c5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610ad057845468ff00000000000000001916680100000000000000001785555b6001600160a01b038b161580610aed57506001600160a01b038a16155b80610aff57506001600160a01b038916155b80610b1157506001600160a01b038816155b80610b2357506001600160a01b038716155b15610b415760405163d92e233d60e01b815260040160405180910390fd5b610b4a8b611870565b600080546001600160a01b038c811673ffffffffffffffffffffffffffffffffffffffff19928316178355600180548d8316908416179055600280548c831690841617815560098054928c169290931691909117909155600388905560045560408051600a808252610160820190925260b49291602082016101408036833701905050905060005b600a811015610c1457610be583826121c2565b610bef90846121d9565b828281518110610c0157610c0161217d565b6020908102919091010152600101610bd2565b50610c2e63116f114960e01b637dac5a0760e11b83611881565b50508315610c7b57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050505050565b6000805460408051632eafe5e760e11b8152905183926001600160a01b031691635d5fcbce9160048083019260209291908290030181865afa158015610cd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf69190612193565b90506000610d056003836121ec565b90506004548111610d195760009250505090565b600454610d26908261220e565b9250505090565b600061059282611936565b610d4433848484611144565b6000610d4e61083d565b90506000610d5c8286610598565b60008381526007602090815260408083206001600160a01b038a1684529091529020909150610d8b90336119ab565b5080600103610e71576000828152600660205260409020610dac90866119ab565b506000828152600a602090815260408083206001600160a01b03891684529091529020548015610e6f576000610de2824261220e565b600954604051633dc12d2360e01b81526001600160a01b038a8116600483015260248201849052929350911690633dc12d2390604401600060405180830381600087803b158015610e3257600080fd5b505af1158015610e46573d6000803e3d6000fd5b5050506000858152600a602090815260408083206001600160a01b038c16845290915281205550505b505b610e7a8261178d565b60405184906001600160a01b0387169033907f392643b1c214ef857ada7fce1cd87c13940ad6883df76dba4808672b7d69c81590600090a45050505050565b604080518082019091526000815260606020820152610ed66115ec565b82516020808501919091206001600160e01b0319908116600090815292825260409283902083518085018552815460e01b9092168252600181018054855181860281018601909652808652929491938581019390830182828015610f5957602002820191906000526020600020905b815481526020019060010190808311610f45575b5050505050815250509050919050565b600080610f746115ec565b6001600160e01b031980861660009081526020838152604080832081518083018352815460e01b90951685526001810180548351818602810186019094528084529697509395909385840193909190830182828015610ff257602002820191906000526020600020905b815481526020019060010190808311610fde575b505050505081525050905080602001515160000361101557600092505050610592565b60208101518151600090611028906119c0565b905060005b825181101561113657818382815181106110495761104961217d565b60200260200101510361112e57600080821161107f57836000815181106110725761107261217d565b60200260200101516110a4565b8361108b60018461220e565b8151811061109b5761109b61217d565b60200260200101515b90506000600185516110b6919061220e565b83106110e85784600186516110cb919061220e565b815181106110db576110db61217d565b602002602001015161110d565b846110f48460016121d9565b815181106111045761110461217d565b60200260200101515b905081891415801561111f5750808914155b15975050505050505050610592565b60010161102d565b506000979650505050505050565b600061114e61083d565b905061115c8186858561131f565b60008181526007602090815260408083206001600160a01b0388168452909152902061118890866114b6565b6104f5576040516315af88af60e31b81526001600160a01b038087166004830152851660248201526044016104ec565b6040805180820190915260008152606060208201526111d56115ec565b6001600160e01b03198084166000908152602092835260409081902081518083018352815460e01b9093168352600181018054835181870281018701909452808452939491938583019392830182828015610f595760200282019190600052602060002090815481526020019060010190808311610f45575050505050815250509050919050565b600061129b826007600061126f61083d565b8152602080820192909252604090810160009081206001600160a01b03891682529092529020906114b6565b949350505050565b60606108ab61046d61083d565b6000818152600660205260408120610592906115e2565b6112cf6114d8565b6001600160a01b0381166112f957604051631e4fbdf760e01b8152600060048201526024016104ec565b6113028161164e565b50565b600081815260066020526040902060609061059290611a97565b60005460405163facd743b60e01b81526001600160a01b0385811660048301529091169063facd743b90602401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190612221565b6113aa57604051631aa1e81560e01b815260040160405180910390fd5b438211806113b9575080824014155b156113d75760405163be5a36cf60e01b815260040160405180910390fd5b60008481526006602052604090206113ef90846114b6565b156114185760405163b3e1875160e01b81526001600160a01b03841660048201526024016104ec565b600154604080516326c0f5d160e21b815290516000926001600160a01b031691639b03d7449160048083019260209291908290030181865afa158015611462573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114869190612193565b90506003548161149691906121d9565b4210156104f5576040516341c86e2f60e01b815260040160405180910390fd5b6001600160a01b038116600090815260018301602052604081205415156105c3565b3361150a7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161461083b5760405163118cdaa760e01b81523360048201526024016104ec565b60008061153f836112b0565b60008054906101000a90046001600160a01b03166001600160a01b0316635d5fcbce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b49190612193565b6115be919061220e565b905060036115cd8260026121c2565b6115d791906121ec565b6105c39060016121d9565b6000610592825490565b60008060ff1961161d60017fdace3fd3d1fbdfd33853f19ba191d28c617e373ec58fc73cf7b58db5aff2c2ab61220e565b60405160200161162f91815260200190565b60408051601f1981840301815291905280516020909101201692915050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60006105c3836001600160a01b038416611aa4565b6000828152600a602090815260408083206001600160a01b03851684529091529020541561170d575050565b6000828152600a602090815260408083206001600160a01b0385811680865291909352818420429055925490516338bb317760e11b81526004810193909352169063717662ee90602401600060405180830381600087803b15801561177157600080fd5b505af1158015611785573d6000803e3d6000fd5b505050505050565b60008181526005602052604090205460ff16156117a75750565b60006117b1610c88565b905060006117be83611936565b9050818110156117cd57505050565b600083815260056020526040808220805460ff191660011790556002548151632cb1043960e11b815291516001600160a01b03909116926359620872926004808201939182900301818387803b15801561182657600080fd5b505af115801561183a573d6000803e3d6000fd5b50506040514392508591507f56d37189df10957afc08d69b74c305bd8e82d9f3a6af80cc3a989a5c082b31ea90600090a3505050565b611878611af3565b61130281611b41565b611889611af3565b60006118936115ec565b6040805180820182526001600160e01b0319868116825260208083018781529189166000908152858252939093208251815463ffffffff191660e09190911c17815590518051949550919390926118f1926001850192910190611c98565b509050507f3665bf9cd0ba4ddceeec259e21dcf8a4510f3b1130bd42e950828e69d85408ba84848460405161192893929190612243565b60405180910390a150505050565b60008061194283611533565b905060008061195085611305565b905060005b81518110156119a15760008282815181106119725761197261217d565b60200260200101519050846119878883610598565b1061199857611995846122a6565b93505b50600101611955565b5090949350505050565b60006105c3836001600160a01b038416611b49565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03198516179052905160009190829081903090611a179085906122bf565b600060405180830381855afa9150503d8060008114611a52576040519150601f19603f3d011682016040523d82523d6000602084013e611a57565b606091505b509150915081611a7a57604051635fbab09b60e11b815260040160405180910390fd5b80806020019051810190611a8e9190612193565b95945050505050565b606060006105c383611c3c565b6000818152600183016020526040812054611aeb57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610592565b506000610592565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661083b57604051631afcd79f60e31b815260040160405180910390fd5b6112cf611af3565b60008181526001830160205260408120548015611c32576000611b6d60018361220e565b8554909150600090611b819060019061220e565b9050808214611be6576000866000018281548110611ba157611ba161217d565b9060005260206000200154905080876000018481548110611bc457611bc461217d565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611bf757611bf76122ee565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610592565b6000915050610592565b606081600001805480602002602001604051908101604052809291908181526020018280548015611c8c57602002820191906000526020600020905b815481526020019060010190808311611c78575b50505050509050919050565b828054828255906000526020600020908101928215611cd3579160200282015b82811115611cd3578251825591602001919060010190611cb8565b50611cdf929150611cfd565b5090565b508054600082559060005260206000209081019061130291905b5b80821115611cdf5760008155600101611cfe565b80356001600160a01b0381168114611d2957600080fd5b919050565b60008060008060808587031215611d4457600080fd5b611d4d85611d12565b9350611d5b60208601611d12565b93969395505050506040820135916060013590565b600060208284031215611d8257600080fd5b5035919050565b60008060408385031215611d9c57600080fd5b82359150611dac60208401611d12565b90509250929050565b80356001600160e01b031981168114611d2957600080fd5b60008060008060608587031215611de357600080fd5b611dec85611db5565b9350611dfa60208601611db5565b9250604085013567ffffffffffffffff80821115611e1757600080fd5b818701915087601f830112611e2b57600080fd5b813581811115611e3a57600080fd5b8860208260051b8501011115611e4f57600080fd5b95989497505060200194505050565b600060208284031215611e7057600080fd5b6105c382611db5565b600080600060608486031215611e8e57600080fd5b611e9784611d12565b95602085013595506040909401359392505050565b60008060008060008060c08789031215611ec557600080fd5b611ece87611d12565b9550611edc60208801611d12565b9450611eea60408801611d12565b9350611ef860608801611d12565b9250611f0660808801611d12565b915060a087013590509295509295509295565b634e487b7160e01b600052604160045260246000fd5b600060208284031215611f4157600080fd5b813567ffffffffffffffff80821115611f5957600080fd5b818401915084601f830112611f6d57600080fd5b813581811115611f7f57611f7f611f19565b604051601f8201601f19908116603f01168101908382118183101715611fa757611fa7611f19565b81604052828152876020848701011115611fc057600080fd5b826020860160208301376000928101602001929092525095945050505050565b602080825282516001600160e01b031916828201528281015160408084015280516060840181905260009291820190839060808601905b808310156120375783518252928401926001929092019190840190612017565b509695505050505050565b6000806040838503121561205557600080fd5b61205e83611db5565b946020939093013593505050565b60008060006060848603121561208157600080fd5b8335925061209160208501611d12565b915061209f60408501611d12565b90509250925092565b6020808252825182820181905260009190848201906040850190845b818110156120e95783516001600160a01b0316835292840192918401916001016120c4565b50909695505050505050565b60006020828403121561210757600080fd5b6105c382611d12565b6001600160e01b0319858116825284166020820152606060408201819052810182905260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561216257600080fd5b8260051b808560808501379190910160800195945050505050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156121a557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610592576105926121ac565b80820180821115610592576105926121ac565b60008261220957634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610592576105926121ac565b60006020828403121561223357600080fd5b815180151581146105c357600080fd5b6001600160e01b031984811682528316602080830191909152606060408301819052835190830181905260009184810191608085019190845b818110156122985784518452938201939282019260010161227c565b509198975050505050505050565b6000600182016122b8576122b86121ac565b5060010190565b6000825160005b818110156122e057602081860181015185830152016122c6565b506000920191825250919050565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220096fad6587d7e602f6d2734ab7028f0e4fa96036047dfd33e248fcc20d80088f64736f6c63430008190033