Source Code
Overview
CELO Balance
CELO Value
$0.00Multichain Info
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
EpochManager
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.7 <0.8.20;
import "@openzeppelin/contracts8/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts8/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts8/access/Ownable.sol";
import "./interfaces/IOracle.sol";
import "../common/UsingRegistry.sol";
import "../../contracts/common/FixidityLib.sol";
import "../../contracts/common/Initializable.sol";
import "../../contracts/common/interfaces/IEpochManager.sol";
import "../../contracts/common/interfaces/ICeloVersionedContract.sol";
import "./interfaces/IEpochManagerInitializer.sol";
/**
* @title Contract used for managing CELO L2 epoch and elections.
* @dev DESIGN_DESICION: we assume that the first epoch on the L2 starts as soon as the system is initialized
* to minimize amount of "limbo blocks" the network should stop relatively close to an epoch number (but with enough time)
* to have time to call the function `EpochInitializer.migrateEpochAndValidators()`
*/
contract EpochManager is
Initializable,
UsingRegistry,
IEpochManager,
ReentrancyGuard,
ICeloVersionedContract,
IEpochManagerInitializer
{
using FixidityLib for FixidityLib.Fraction;
struct Epoch {
uint256 firstBlock;
uint256 lastBlock;
uint256 startTimestamp;
uint256 rewardsBlock;
}
enum EpochProcessStatus {
NotStarted,
Started,
IndivudualGroupsProcessing
}
struct EpochProcessState {
EpochProcessStatus status;
uint256 perValidatorReward; // The per validator epoch reward.
uint256 totalRewardsVoter; // The total rewards to voters.
uint256 totalRewardsCommunity; // The total community reward.
uint256 totalRewardsCarbonFund; // The total carbon offsetting partner reward.
}
bool public isSystemInitialized;
// the length of an epoch in seconds
uint256 public epochDuration;
uint256 public firstKnownEpoch;
uint256 internal currentEpochNumber;
address public oracleAddress;
address[] public electedAccounts;
mapping(address => uint256) public processedGroups;
EpochProcessState public epochProcessing;
mapping(uint256 => Epoch) internal epochs;
mapping(address => uint256) public validatorPendingPayments;
// Electeds in the L1 assumed signers can not change during the epoch
// so we keep a copy
address[] public electedSigners;
uint256 public toProcessGroups = 0;
/**
* @notice Event emited when epochProcessing has begun.
* @param epochNumber The epoch number that is being processed.
*/
event EpochProcessingStarted(uint256 indexed epochNumber);
/**
* @notice Event emited when epochProcessing has ended.
* @param epochNumber The epoch number that is finished being processed.
*/
event EpochProcessingEnded(uint256 indexed epochNumber);
/**
* @notice Event emited when a new epoch duration is set.
* @param newEpochDuration The new epoch duration.
*/
event EpochDurationSet(uint256 indexed newEpochDuration);
/**
* @notice Event emited when a new oracle address is set.
* @param newOracleAddress The new oracle address.
*/
event OracleAddressSet(address indexed newOracleAddress);
/**
* @notice Emitted when an epoch payment is sent.
* @param validator Address of the validator.
* @param validatorPayment Amount of cUSD sent to the validator.
* @param group Address of the validator's group.
* @param groupPayment Amount of cUSD sent to the group.
*/
event ValidatorEpochPaymentDistributed(
address indexed validator,
uint256 validatorPayment,
address indexed group,
uint256 groupPayment,
address indexed beneficiary,
uint256 delegatedPayment
);
/**
* @notice Emitted when group is marked for processing.
* @param group Address of the group to be processed.
* @param epochNumber The epoch number for which the group gets marked for processing.
*/
event GroupMarkedForProcessing(address indexed group, uint256 indexed epochNumber);
/**
* @notice Emitted when group is processed.
* @param group Address of the processed group.
* @param epochNumber The epoch number for which the group gets processed.
*/
event GroupProcessed(address indexed group, uint256 indexed epochNumber);
/**
* @notice Throws if called by other than EpochManagerEnabler contract.
*/
modifier onlyEpochManagerEnabler() {
require(
msg.sender == registry.getAddressForOrDie(EPOCH_MANAGER_ENABLER_REGISTRY_ID),
"msg.sender is not Enabler"
);
_;
}
/**
* @notice Throws if called when EpochManager system has not yet been initalized.
*/
modifier onlySystemAlreadyInitialized() {
require(systemAlreadyInitialized(), "Epoch system not initialized");
_;
}
/**
* @notice Sets initialized == true on implementation contracts
* @param test Set to true to skip implementation initialization
*/
constructor(bool test) Initializable(test) {}
/**
* @notice Used in place of the constructor to allow the contract to be upgradable via proxy.
* @param registryAddress The address of the registry core smart contract.
* @param newEpochDuration The duration of an epoch in seconds.
*/
function initialize(address registryAddress, uint256 newEpochDuration) external initializer {
_transferOwnership(msg.sender);
setRegistry(registryAddress);
setEpochDuration(newEpochDuration);
setOracleAddress(registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID));
}
/**
* @notice Initializes the EpochManager system, allowing it to start processing epoch
* and distributing the epoch rewards.
* @dev Can only be called by the EpochManagerEnabler contract.
*/
function initializeSystem(
uint256 firstEpochNumber,
uint256 firstEpochBlock,
address[] memory firstElected
) external onlyEpochManagerEnabler {
require(
getCeloToken().balanceOf(registry.getAddressForOrDie(CELO_UNRELEASED_TREASURY_REGISTRY_ID)) >
0,
"CeloUnreleasedTreasury not yet funded."
);
require(!systemAlreadyInitialized(), "Epoch system already initialized");
require(firstEpochNumber > 0, "First epoch number must be greater than 0");
require(firstEpochBlock > 0, "First epoch block must be greater than 0");
require(
firstEpochBlock <= block.number,
"First epoch block must be less or equal than current block"
);
require(firstElected.length > 0, "First elected validators must be greater than 0");
isSystemInitialized = true;
firstKnownEpoch = firstEpochNumber;
currentEpochNumber = firstEpochNumber;
Epoch storage _currentEpoch = epochs[currentEpochNumber];
_currentEpoch.firstBlock = firstEpochBlock;
_currentEpoch.startTimestamp = block.timestamp;
electedAccounts = firstElected;
_setElectedSigners(firstElected);
}
/**
* @notice Starts processing an epoch and allocates funds to the beneficiaries.
* @dev Epoch rewards are frozen at the time of execution.
* @dev Can only be called once the system is initialized.
*/
function startNextEpochProcess() external nonReentrant onlySystemAlreadyInitialized {
require(isTimeForNextEpoch(), "Epoch is not ready to start");
require(
epochProcessing.status == EpochProcessStatus.NotStarted,
"Epoch process is already started"
);
require(!isEpochProcessingStarted(), "Epoch process is already started");
epochProcessing.status = EpochProcessStatus.Started;
epochs[currentEpochNumber].rewardsBlock = block.number;
// calculate rewards
getEpochRewards().updateTargetVotingYield();
(
uint256 perValidatorReward,
uint256 totalRewardsVoter,
uint256 totalRewardsCommunity,
uint256 totalRewardsCarbonFund
) = getEpochRewards().calculateTargetEpochRewards();
epochProcessing.perValidatorReward = perValidatorReward;
epochProcessing.totalRewardsVoter = totalRewardsVoter;
epochProcessing.totalRewardsCommunity = totalRewardsCommunity;
epochProcessing.totalRewardsCarbonFund = totalRewardsCarbonFund;
allocateValidatorsRewards();
emit EpochProcessingStarted(currentEpochNumber);
}
/**
* @notice Starts individual processing of the elected groups.
* As second step it is necessary to call processGroup
*/
function setToProcessGroups() external {
require(isOnEpochProcess(), "Epoch process is not started");
EpochProcessState storage _epochProcessing = epochProcessing;
_epochProcessing.status = EpochProcessStatus.IndivudualGroupsProcessing;
IValidators validators = getValidators();
IElection election = getElection();
IScoreReader scoreReader = getScoreReader();
require(
electedAccounts.length == electedSigners.length,
"Elected accounts and signers of different lengths."
);
for (uint i = 0; i < electedAccounts.length; i++) {
address group = validators.getValidatorsGroup(electedAccounts[i]);
if (processedGroups[group] == 0) {
toProcessGroups++;
uint256 groupScore = scoreReader.getGroupScore(group);
// We need to precompute epoch rewards for each group since computation depends on total active votes for all groups.
uint256 epochRewards = election.getGroupEpochRewardsBasedOnScore(
group,
_epochProcessing.totalRewardsVoter,
groupScore
);
processedGroups[group] = epochRewards == 0 ? type(uint256).max : epochRewards;
emit GroupMarkedForProcessing(group, currentEpochNumber);
}
}
}
/**
* @notice Processes the rewards for a list of groups. For last group it will also finalize the epoch.
* @param groups List of validator groups to be processed.
* @param lessers List of validator groups that hold less votes that indexed group.
* @param greaters List of validator groups that hold more votes that indexed group.
*/
function processGroups(
address[] calldata groups,
address[] calldata lessers,
address[] calldata greaters
) external {
for (uint i = 0; i < groups.length; i++) {
processGroup(groups[i], lessers[i], greaters[i]);
}
}
/**
* @notice Processes the rewards for a group. For last group it will also finalize the epoch.
* @param group The group to process.
* @param lesser The group with less votes than the indexed group.
* @param greater The group with more votes than the indexed group.
*/
function processGroup(address group, address lesser, address greater) public {
EpochProcessState storage _epochProcessing = epochProcessing;
require(isIndividualProcessing(), "Indivudual epoch process is not started");
require(toProcessGroups > 0, "no more groups to process");
uint256 epochRewards = processedGroups[group];
// checks that group is actually from elected group
require(epochRewards > 0, "group not from current elected set");
IElection election = getElection();
if (epochRewards != type(uint256).max) {
election.distributeEpochRewards(group, epochRewards, lesser, greater);
}
delete processedGroups[group];
toProcessGroups--;
emit GroupProcessed(group, currentEpochNumber);
if (toProcessGroups == 0) {
_finishEpochHelper(_epochProcessing, election);
}
}
/**
* @notice Finishes processing an epoch and releasing funds to the beneficiaries.
* @param groups List of validator groups to be processed.
* @param lessers List of validator groups that hold less votes that indexed group.
* @param greaters List of validator groups that hold more votes that indexed group.
*/
function finishNextEpochProcess(
address[] calldata groups,
address[] calldata lessers,
address[] calldata greaters
) external virtual nonReentrant {
require(isOnEpochProcess(), "Epoch process is not started");
require(toProcessGroups == 0, "Can't finish epoch while individual groups are being processed");
EpochProcessState storage _epochProcessing = epochProcessing;
uint256 _toProcessGroups = 0;
IValidators validators = getValidators();
IElection election = getElection();
IScoreReader scoreReader = getScoreReader();
require(
electedAccounts.length == electedSigners.length,
"Elected accounts and signers of different lengths."
);
for (uint i = 0; i < electedAccounts.length; i++) {
address group = validators.getValidatorsGroup(electedAccounts[i]);
if (processedGroups[group] == 0) {
_toProcessGroups++;
uint256 groupScore = scoreReader.getGroupScore(group);
// We need to precompute epoch rewards for each group since computation depends on total active votes for all groups.
uint256 epochRewards = election.getGroupEpochRewardsBasedOnScore(
group,
_epochProcessing.totalRewardsVoter,
groupScore
);
processedGroups[group] = epochRewards == 0 ? type(uint256).max : epochRewards;
}
delete electedAccounts[i];
delete electedSigners[i];
}
require(_toProcessGroups == groups.length, "number of groups does not match");
for (uint i = 0; i < groups.length; i++) {
uint256 epochRewards = processedGroups[groups[i]];
// checks that group is actually from elected group
require(epochRewards > 0, "group not from current elected set");
if (epochRewards != type(uint256).max) {
election.distributeEpochRewards(groups[i], epochRewards, lessers[i], greaters[i]);
}
delete processedGroups[groups[i]];
emit GroupProcessed(groups[i], currentEpochNumber);
}
_finishEpochHelper(_epochProcessing, election);
}
/**
* @notice Sends the allocated epoch payment to a validator, their group, and
* delegation beneficiary.
* @param validator Account of the validator.
* @dev Can only be called once the system is initialized.
*/
function sendValidatorPayment(address validator) external onlySystemAlreadyInitialized {
FixidityLib.Fraction memory totalPayment = FixidityLib.newFixed(
validatorPendingPayments[validator]
);
validatorPendingPayments[validator] = 0;
IValidators validators = getValidators();
address group = validators.getValidatorsGroup(validator);
(, uint256 commissionUnwrapped, , , , , ) = validators.getValidatorGroup(group);
uint256 groupPayment = totalPayment.multiply(FixidityLib.wrap(commissionUnwrapped)).fromFixed();
FixidityLib.Fraction memory remainingPayment = FixidityLib.newFixed(
totalPayment.fromFixed() - groupPayment
);
(address beneficiary, uint256 delegatedFraction) = getAccounts().getPaymentDelegation(
validator
);
uint256 delegatedPayment = remainingPayment
.multiply(FixidityLib.wrap(delegatedFraction))
.fromFixed();
uint256 validatorPayment = remainingPayment.fromFixed() - delegatedPayment;
IERC20 stableToken = IERC20(getStableToken());
if (validatorPayment > 0) {
require(stableToken.transfer(validator, validatorPayment), "transfer failed to validator");
}
if (groupPayment > 0) {
require(stableToken.transfer(group, groupPayment), "transfer failed to validator group");
}
if (delegatedPayment > 0) {
require(stableToken.transfer(beneficiary, delegatedPayment), "transfer failed to delegatee");
}
emit ValidatorEpochPaymentDistributed(
validator,
validatorPayment,
group,
groupPayment,
beneficiary,
delegatedPayment
);
}
/**
* @notice Returns the epoch info for the current epoch.
* @return firstEpoch The first block of the current epoch.
* @return lastBlock The last block of the current epoch.
* @return startTimestamp The starting timestamp of the current epoch.
* @return rewardsBlock The reward block of the current epoch.
*/
function getCurrentEpoch()
external
view
onlySystemAlreadyInitialized
returns (uint256, uint256, uint256, uint256)
{
return getEpochByNumber(currentEpochNumber);
}
/**
* @return The current epoch number.
* @dev Can only be called once the system is initialized.
*/
function getCurrentEpochNumber() external view onlySystemAlreadyInitialized returns (uint256) {
return currentEpochNumber;
}
/**
* @return The latest epoch processing state.
*/
function getEpochProcessingState()
external
view
returns (uint256, uint256, uint256, uint256, uint256)
{
EpochProcessState storage _epochProcessing = epochProcessing;
return (
uint256(_epochProcessing.status),
_epochProcessing.perValidatorReward,
_epochProcessing.totalRewardsVoter,
_epochProcessing.totalRewardsCommunity,
_epochProcessing.totalRewardsCarbonFund
);
}
/**
* @notice Used to block select functions in blockable contracts.
* @return Whether or not the blockable functions are blocked.
*/
function isBlocked() external view returns (bool) {
return isEpochProcessingStarted();
}
/**
* @return The number of elected accounts in the current set.
*/
function numberOfElectedInCurrentSet()
external
view
onlySystemAlreadyInitialized
returns (uint256)
{
return electedAccounts.length;
}
/**
* @return The list of currently elected validators.
*/
function getElectedAccounts()
external
view
onlySystemAlreadyInitialized
returns (address[] memory)
{
return electedAccounts;
}
/**
* @notice Returns the currently elected account at a specified index.
* @param index The index of the currently elected account.
*/
function getElectedAccountByIndex(
uint256 index
) external view onlySystemAlreadyInitialized returns (address) {
return electedAccounts[index];
}
/**
* @return The list of the validator signers of elected validators.
*/
function getElectedSigners()
external
view
onlySystemAlreadyInitialized
returns (address[] memory)
{
return electedSigners;
}
/**
* @notice Returns the currently elected signer address at a specified index.
* @param index The index of the currently elected signer.
*/
function getElectedSignerByIndex(
uint256 index
) external view onlySystemAlreadyInitialized returns (address) {
return electedSigners[index];
}
/**
* @param epoch The epoch number of interest.
* @return The First block of the specified epoch.
*/
function getFirstBlockAtEpoch(uint256 epoch) external view returns (uint256) {
require(epoch >= firstKnownEpoch, "Epoch not known");
require(epoch <= currentEpochNumber, "Epoch not created yet");
return epochs[epoch].firstBlock;
}
/**
* @param epoch The epoch number of interest.
* @return The last block of the specified epoch.
*/
function getLastBlockAtEpoch(uint256 epoch) external view returns (uint256) {
require(epoch >= firstKnownEpoch, "Epoch not known");
require(epoch < currentEpochNumber, "Epoch not finished yet");
return epochs[epoch].lastBlock;
}
/**
* @notice Returns the epoch number of a specified blockNumber.
* @param _blockNumber Block number of the epoch info is retreived.
*/
function getEpochNumberOfBlock(
uint256 _blockNumber
) external view onlySystemAlreadyInitialized returns (uint256) {
(uint256 _epochNumber, , , , ) = _getEpochByBlockNumber(_blockNumber);
return _epochNumber;
}
/**
* @notice Returns the epoch info of a specified blockNumber.
* @param _blockNumber Block number of the epoch info is retreived.
* @return firstEpoch The first block of the given block number.
* @return lastBlock The first block of the given block number.
* @return startTimestamp The starting timestamp of the given block number.
* @return rewardsBlock The reward block of the given block number.
*/
function getEpochByBlockNumber(
uint256 _blockNumber
) external view onlySystemAlreadyInitialized returns (uint256, uint256, uint256, uint256) {
(
,
uint256 _firstBlock,
uint256 _lastBlock,
uint256 _startTimestamp,
uint256 _rewardsBlock
) = _getEpochByBlockNumber(_blockNumber);
return (_firstBlock, _lastBlock, _startTimestamp, _rewardsBlock);
}
/**
* @notice Returns the storage, major, minor, and patch version of the contract.
* @return Storage version of the contract.
* @return Major version of the contract.
* @return Minor version of the contract.
* @return Patch version of the contract.
*/
function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) {
return (1, 1, 0, 0);
}
/**
* @notice Sets the time duration of an epoch.
* @param newEpochDuration The duration of an epoch in seconds.
* @dev Can only be set by owner.
*/
function setEpochDuration(uint256 newEpochDuration) public onlyOwner {
require(newEpochDuration > 0, "New epoch duration must be greater than zero.");
require(!isOnEpochProcess(), "Cannot change epoch duration during processing.");
epochDuration = newEpochDuration;
emit EpochDurationSet(newEpochDuration);
}
/**
* @notice Sets the address of the Oracle used by this contract.
* @param newOracleAddress The address of the new oracle.
* @dev Can only be set by owner.
*/
function setOracleAddress(address newOracleAddress) public onlyOwner {
require(newOracleAddress != address(0), "Cannot set address zero as the Oracle.");
require(newOracleAddress != oracleAddress, "Oracle address cannot be the same.");
require(!isOnEpochProcess(), "Cannot change oracle address during epoch processing.");
oracleAddress = newOracleAddress;
emit OracleAddressSet(newOracleAddress);
}
/**
* @return Whether epoch is being processed by individualy group by group.
*/
function isIndividualProcessing() public view returns (bool) {
return epochProcessing.status == EpochProcessStatus.IndivudualGroupsProcessing;
}
/**
* @return Whether epoch process has been started.
*/
function isEpochProcessingStarted() public view returns (bool) {
return isOnEpochProcess() || isIndividualProcessing();
}
/**
* @return Whether or not the next epoch can be processed.
*/
function isTimeForNextEpoch() public view returns (bool) {
return block.timestamp >= epochs[currentEpochNumber].startTimestamp + epochDuration;
}
/**
* @return Whether or not the current epoch is being processed.
*/
function isOnEpochProcess() public view returns (bool) {
return epochProcessing.status == EpochProcessStatus.Started;
}
/**
* @return Whether or not the EpochManager contract has been activated to start processing epochs.
*/
function systemAlreadyInitialized() public view returns (bool) {
return initialized && isSystemInitialized;
}
/**
* @notice Returns the epoch info of a specified epoch.
* @param epochNumber Epoch number where the epoch info is retreived.
* @return firstEpoch The first block of the given epoch.
* @return lastBlock The first block of the given epoch.
* @return startTimestamp The starting timestamp of the given epoch.
* @return rewardsBlock The reward block of the given epoch.
*/
function getEpochByNumber(
uint256 epochNumber
) public view onlySystemAlreadyInitialized returns (uint256, uint256, uint256, uint256) {
Epoch memory _epoch = epochs[epochNumber];
return (_epoch.firstBlock, _epoch.lastBlock, _epoch.startTimestamp, _epoch.rewardsBlock);
}
/**
* @notice Allocates rewards to elected validator accounts.
*/
function allocateValidatorsRewards() internal {
uint256 totalRewards = 0;
IScoreReader scoreReader = getScoreReader();
IValidators validators = getValidators();
EpochProcessState storage _epochProcessing = epochProcessing;
for (uint i = 0; i < electedAccounts.length; i++) {
uint256 validatorScore = scoreReader.getValidatorScore(electedAccounts[i]);
uint256 validatorReward = validators.computeEpochReward(
electedAccounts[i],
validatorScore,
_epochProcessing.perValidatorReward
);
validatorPendingPayments[electedAccounts[i]] += validatorReward;
totalRewards += validatorReward;
}
if (totalRewards == 0) {
return;
}
// Mint all cUSD required for payment and the corresponding CELO
validators.mintStableToEpochManager(totalRewards);
(uint256 numerator, uint256 denominator) = IOracle(oracleAddress).getExchangeRate(
address(getStableToken())
);
uint256 CELOequivalent = (numerator * totalRewards) / denominator;
getCeloUnreleasedTreasury().release(
registry.getAddressForOrDie(RESERVE_REGISTRY_ID),
CELOequivalent
);
}
/**
* @notice Updates the list of elected validator signers.
*/
function _setElectedSigners(address[] memory _elected) internal {
require(electedAccounts.length > 0, "Elected list length cannot be zero.");
IAccounts accounts = getAccounts();
electedSigners = new address[](_elected.length);
for (uint i = 0; i < _elected.length; i++) {
electedSigners[i] = accounts.getValidatorSigner(_elected[i]);
}
}
/**
* @notice Finishes processing an epoch and releasing funds to the beneficiaries.
* @param _epochProcessing The current epoch processing state.
* @param election The Election contract.
*/
function _finishEpochHelper(
EpochProcessState storage _epochProcessing,
IElection election
) internal {
// finalize epoch
// last block should be the block before and timestamp from previous block
epochs[currentEpochNumber].lastBlock = block.number - 1;
currentEpochNumber++;
// start new epoch
epochs[currentEpochNumber].firstBlock = block.number;
epochs[currentEpochNumber].startTimestamp = block.timestamp;
// run elections
address[] memory _newlyElected = election.electValidatorAccounts();
electedAccounts = _newlyElected;
_setElectedSigners(_newlyElected);
ICeloUnreleasedTreasury celoUnreleasedTreasury = getCeloUnreleasedTreasury();
celoUnreleasedTreasury.release(
registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID),
_epochProcessing.totalRewardsCommunity
);
celoUnreleasedTreasury.release(
getEpochRewards().carbonOffsettingPartner(),
_epochProcessing.totalRewardsCarbonFund
);
_epochProcessing.status = EpochProcessStatus.NotStarted;
_epochProcessing.perValidatorReward = 0;
_epochProcessing.totalRewardsVoter = 0;
_epochProcessing.totalRewardsCommunity = 0;
_epochProcessing.totalRewardsCarbonFund = 0;
emit EpochProcessingEnded(currentEpochNumber - 1);
}
/**
* @notice Returns the epoch info of a specified blockNumber.
* @dev This function is here for backward compatibility. It is rather gas heavy and can run out of gas.
* @param _blockNumber Block number of the epoch info is retreived.
* @return firstEpoch The first block of the given block number.
* @return lastBlock The first block of the given block number.
* @return startTimestamp The starting timestamp of the given block number.
* @return rewardsBlock The reward block of the given block number.
*/
function _getEpochByBlockNumber(
uint256 _blockNumber
)
internal
view
onlySystemAlreadyInitialized
returns (uint256, uint256, uint256, uint256, uint256)
{
require(_blockNumber <= block.number, "Invalid blockNumber. Value too high.");
(uint256 _firstBlockOfFirstEpoch, , , ) = getEpochByNumber(firstKnownEpoch);
require(_blockNumber >= _firstBlockOfFirstEpoch, "Invalid blockNumber. Value too low.");
uint256 _firstBlockOfCurrentEpoch = epochs[currentEpochNumber].firstBlock;
if (_blockNumber >= _firstBlockOfCurrentEpoch) {
(
uint256 _firstBlock,
uint256 _lastBlock,
uint256 _startTimestamp,
uint256 _rewardsBlock
) = getEpochByNumber(currentEpochNumber);
return (currentEpochNumber, _firstBlock, _lastBlock, _startTimestamp, _rewardsBlock);
}
uint256 left = firstKnownEpoch;
uint256 right = currentEpochNumber - 1;
while (left <= right) {
uint256 mid = (left + right) / 2;
uint256 _epochFirstBlock = epochs[mid].firstBlock;
uint256 _epochLastBlock = epochs[mid].lastBlock;
if (_blockNumber >= _epochFirstBlock && _blockNumber <= _epochLastBlock) {
Epoch memory _epoch = epochs[mid];
return (
mid,
_epoch.firstBlock,
_epoch.lastBlock,
_epoch.startTimestamp,
_epoch.rewardsBlock
);
} else if (_blockNumber < _epochFirstBlock) {
right = mid - 1;
} else {
left = mid + 1;
}
}
revert("No matching epoch found for the given block number.");
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface ISortedOracles {
function addOracle(address, address) external;
function removeOracle(address, address, uint256) external;
function report(address, uint256, address, address) external;
function removeExpiredReports(address, uint256) external;
function isOldestReportExpired(address token) external view returns (bool, address);
function numRates(address) external view returns (uint256);
function medianRate(address) external view returns (uint256, uint256);
function numTimestamps(address) external view returns (uint256);
function medianTimestamp(address) external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IValidators {
function registerValidator(
bytes calldata,
bytes calldata,
bytes calldata
) external returns (bool);
function registerValidatorNoBls(bytes calldata ecdsaPublicKey) external returns (bool);
function deregisterValidator(uint256) external returns (bool);
function affiliate(address) external returns (bool);
function deaffiliate() external returns (bool);
function updateBlsPublicKey(bytes calldata, bytes calldata) external returns (bool);
function registerValidatorGroup(uint256) external returns (bool);
function deregisterValidatorGroup(uint256) external returns (bool);
function addMember(address) external returns (bool);
function addFirstMember(address, address, address) external returns (bool);
function removeMember(address) external returns (bool);
function reorderMember(address, address, address) external returns (bool);
function updateCommission() external;
function setNextCommissionUpdate(uint256) external;
function resetSlashingMultiplier() external;
// only owner
function setCommissionUpdateDelay(uint256) external;
function setMaxGroupSize(uint256) external returns (bool);
function setMembershipHistoryLength(uint256) external returns (bool);
function setValidatorScoreParameters(uint256, uint256) external returns (bool);
function setGroupLockedGoldRequirements(uint256, uint256) external returns (bool);
function setValidatorLockedGoldRequirements(uint256, uint256) external returns (bool);
function setSlashingMultiplierResetPeriod(uint256) external;
function setDowntimeGracePeriod(uint256 value) external;
// only registered contract
function updateEcdsaPublicKey(address, address, bytes calldata) external returns (bool);
function updatePublicKeys(
address,
address,
bytes calldata,
bytes calldata,
bytes calldata
) external returns (bool);
function mintStableToEpochManager(uint256 amount) external;
// only VM
function updateValidatorScoreFromSigner(address, uint256) external;
function distributeEpochPaymentsFromSigner(address, uint256) external returns (uint256);
// only slasher
function forceDeaffiliateIfValidator(address) external;
function halveSlashingMultiplier(address) external;
// view functions
function maxGroupSize() external view returns (uint256);
function downtimeGracePeriod() external view returns (uint256);
function getCommissionUpdateDelay() external view returns (uint256);
function getValidatorScoreParameters() external view returns (uint256, uint256);
function getMembershipHistory(
address
) external view returns (uint256[] memory, address[] memory, uint256, uint256);
function calculateEpochScore(uint256) external view returns (uint256);
function calculateGroupEpochScore(uint256[] calldata) external view returns (uint256);
function getAccountLockedGoldRequirement(address) external view returns (uint256);
function meetsAccountLockedGoldRequirements(address) external view returns (bool);
function getValidatorBlsPublicKeyFromSigner(address) external view returns (bytes memory);
function getValidator(
address account
) external view returns (bytes memory, bytes memory, address, uint256, address);
function getValidatorsGroup(address account) external view returns (address affiliation);
function getValidatorGroup(
address
)
external
view
returns (address[] memory, uint256, uint256, uint256, uint256[] memory, uint256, uint256);
function getGroupNumMembers(address) external view returns (uint256);
function getTopGroupValidators(address, uint256) external view returns (address[] memory);
function getTopGroupValidatorsAccounts(address, uint256) external view returns (address[] memory);
function getGroupsNumMembers(
address[] calldata accounts
) external view returns (uint256[] memory);
function getNumRegisteredValidators() external view returns (uint256);
function groupMembershipInEpoch(address, uint256, uint256) external view returns (address);
function getValidatorLockedGoldRequirements() external view returns (uint256, uint256);
function getGroupLockedGoldRequirements() external view returns (uint256, uint256);
function getRegisteredValidators() external view returns (address[] memory);
function getRegisteredValidatorGroups() external view returns (address[] memory);
function isValidatorGroup(address) external view returns (bool);
function isValidator(address) external view returns (bool);
function getValidatorGroupSlashingMultiplier(address) external view returns (uint256);
function getMembershipInLastEpoch(address) external view returns (address);
function getMembershipInLastEpochFromSigner(address) external view returns (address);
function computeEpochReward(
address account,
uint256 score,
uint256 maxPayment
) external view returns (uint256);
function getMembershipHistoryLength() external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface ILockedGold {
function lock() external payable;
function incrementNonvotingAccountBalance(address, uint256) external;
function decrementNonvotingAccountBalance(address, uint256) external;
function unlock(uint256) external;
function relock(uint256, uint256) external;
function withdraw(uint256) external;
function slash(
address account,
uint256 penalty,
address reporter,
uint256 reward,
address[] calldata lessers,
address[] calldata greaters,
uint256[] calldata indices
) external;
function addSlasher(string calldata slasherIdentifier) external;
function getAccountTotalLockedGold(address) external view returns (uint256);
function getTotalLockedGold() external view returns (uint256);
function getPendingWithdrawals(
address
) external view returns (uint256[] memory, uint256[] memory);
function getPendingWithdrawal(
address account,
uint256 index
) external view returns (uint256, uint256);
function getTotalPendingWithdrawals(address) external view returns (uint256);
function isSlasher(address) external view returns (bool);
function getAccountTotalDelegatedFraction(address account) external view returns (uint256);
function getAccountTotalGovernanceVotingPower(address account) external view returns (uint256);
function unlockingPeriod() external view returns (uint256);
function getAccountNonvotingLockedGold(address account) external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface ILockedCelo {
function lock() external payable;
function incrementNonvotingAccountBalance(address, uint256) external;
function decrementNonvotingAccountBalance(address, uint256) external;
function unlock(uint256) external;
function relock(uint256, uint256) external;
function withdraw(uint256) external;
function slash(
address account,
uint256 penalty,
address reporter,
uint256 reward,
address[] calldata lessers,
address[] calldata greaters,
uint256[] calldata indices
) external;
function addSlasher(string calldata slasherIdentifier) external;
function getAccountNonvotingLockedGold(address account) external view returns (uint256);
function getAccountTotalLockedCelo(address) external view returns (uint256);
function getTotalLockedCelo() external view returns (uint256);
function getPendingWithdrawals(
address
) external view returns (uint256[] memory, uint256[] memory);
function getPendingWithdrawal(
address account,
uint256 index
) external view returns (uint256, uint256);
function getTotalPendingWithdrawals(address) external view returns (uint256);
function isSlasher(address) external view returns (bool);
function getAccountTotalDelegatedFraction(address account) external view returns (uint256);
function getAccountTotalGovernanceVotingPower(address account) external view returns (uint256);
function unlockingPeriod() external view returns (uint256);
function getAccountNonvotingLockedCelo(address account) external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IGovernance {
function removeVotesWhenRevokingDelegatedVotes(
address account,
uint256 maxAmountAllowed
) external;
function votePartially(
uint256 proposalId,
uint256 index,
uint256 yesVotes,
uint256 noVotes,
uint256 abstainVotes
) external returns (bool);
function setConstitution(address destination, bytes4 functionId, uint256 threshold) external;
function isVoting(address) external view returns (bool);
function getAmountOfGoldUsedForVoting(address account) external view returns (uint256);
function getProposal(
uint256 proposalId
) external view returns (address, uint256, uint256, uint256, string memory, uint256, bool);
function getReferendumStageDuration() external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IEpochRewards {
function updateTargetVotingYield() external;
function isReserveLow() external view returns (bool);
function calculateTargetEpochRewards() external view returns (uint256, uint256, uint256, uint256);
function getTargetVotingYieldParameters() external view returns (uint256, uint256, uint256);
function getRewardsMultiplierParameters() external view returns (uint256, uint256, uint256);
function getCommunityRewardFraction() external view returns (uint256);
function getCarbonOffsettingFraction() external view returns (uint256);
function getTargetVotingGoldFraction() external view returns (uint256);
function getRewardsMultiplier() external view returns (uint256);
function carbonOffsettingPartner() external view returns (address);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IElection {
function vote(address, uint256, address, address) external returns (bool);
function activate(address) external returns (bool);
function revokeActive(address, uint256, address, address, uint256) external returns (bool);
function revokeAllActive(address, address, address, uint256) external returns (bool);
function revokePending(address, uint256, address, address, uint256) external returns (bool);
function markGroupIneligible(address) external;
function markGroupEligible(address, address, address) external;
function allowedToVoteOverMaxNumberOfGroups(address) external returns (bool);
function forceDecrementVotes(
address,
uint256,
address[] calldata,
address[] calldata,
uint256[] calldata
) external returns (uint256);
function setAllowedToVoteOverMaxNumberOfGroups(bool flag) external;
// only owner
function setElectableValidators(uint256, uint256) external returns (bool);
function setMaxNumGroupsVotedFor(uint256) external returns (bool);
function setElectabilityThreshold(uint256) external returns (bool);
// only VM
function distributeEpochRewards(address, uint256, address, address) external;
// view functions
function electValidatorSigners() external view returns (address[] memory);
function electValidatorAccounts() external view returns (address[] memory);
function electNValidatorSigners(uint256, uint256) external view returns (address[] memory);
function electNValidatorAccounts(uint256, uint256) external view returns (address[] memory);
function getElectableValidators() external view returns (uint256, uint256);
function getElectabilityThreshold() external view returns (uint256);
function getNumVotesReceivable(address) external view returns (uint256);
function getTotalVotes() external view returns (uint256);
function getActiveVotes() external view returns (uint256);
function getTotalVotesByAccount(address) external view returns (uint256);
function getPendingVotesForGroupByAccount(address, address) external view returns (uint256);
function getActiveVotesForGroupByAccount(address, address) external view returns (uint256);
function getTotalVotesForGroupByAccount(address, address) external view returns (uint256);
function getActiveVoteUnitsForGroupByAccount(address, address) external view returns (uint256);
function getTotalVotesForGroup(address) external view returns (uint256);
function getActiveVotesForGroup(address) external view returns (uint256);
function getPendingVotesForGroup(address) external view returns (uint256);
function getGroupEligibility(address) external view returns (bool);
function getGroupEpochRewards(
address,
uint256,
uint256[] calldata
) external view returns (uint256);
function getGroupEpochRewardsBasedOnScore(
address group,
uint256 totalEpochRewards,
uint256 groupScore
) external view returns (uint256);
function getGroupsVotedForByAccount(address) external view returns (address[] memory);
function getEligibleValidatorGroups() external view returns (address[] memory);
function getTotalVotesForEligibleValidatorGroups()
external
view
returns (address[] memory, uint256[] memory);
function getCurrentValidatorSigners() external view returns (address[] memory);
function canReceiveVotes(address, uint256) external view returns (bool);
function hasActivatablePendingVotes(address, address) external view returns (bool);
function validatorSignerAddressFromCurrentSet(uint256 index) external view returns (address);
function numberValidatorsInCurrentSet() external view returns (uint256);
function owner() external view returns (address);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IRegistry {
function setAddressFor(string calldata, address) external;
function getAddressForOrDie(bytes32) external view returns (address);
function getAddressFor(bytes32) external view returns (address);
function getAddressForStringOrDie(string calldata identifier) external view returns (address);
function getAddressForString(string calldata identifier) external view returns (address);
function isOneOf(bytes32[] calldata, address) external view returns (bool);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IFreezer {
function freeze(address target) external;
function unfreeze(address target) external;
function isFrozen(address) external view returns (bool);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IFeeHandlerSeller {
function sell(
address sellTokenAddress,
address buyTokenAddress,
uint256 amount,
uint256 minAmount
) external returns (uint256);
// in case some funds need to be returned or moved to another contract
function transfer(address token, uint256 amount, address to) external returns (bool);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IFeeCurrencyWhitelist {
function initialize() external;
function addToken(address) external;
function getWhitelist() external view returns (address[] memory);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IEpochManager {
function initializeSystem(
uint256 firstEpochNumber,
uint256 firstEpochBlock,
address[] calldata firstElected
) external;
function startNextEpochProcess() external;
function finishNextEpochProcess(
address[] calldata groups,
address[] calldata lessers,
address[] calldata greaters
) external;
function setToProcessGroups() external;
function processGroup(address group, address lesser, address greater) external;
function sendValidatorPayment(address) external;
function getCurrentEpoch() external view returns (uint256, uint256, uint256, uint256);
function getEpochByNumber(
uint256 epochNumber
) external view returns (uint256, uint256, uint256, uint256);
function getEpochByBlockNumber(
uint256 blockNumber
) external view returns (uint256, uint256, uint256, uint256);
function getEpochNumberOfBlock(uint256) external view returns (uint256);
function getCurrentEpochNumber() external view returns (uint256);
function numberOfElectedInCurrentSet() external view returns (uint256);
function getElectedAccounts() external view returns (address[] memory);
function getElectedAccountByIndex(uint256 index) external view returns (address);
function getElectedSigners() external view returns (address[] memory);
function getElectedSignerByIndex(uint256 index) external view returns (address);
function epochDuration() external view returns (uint256);
function firstKnownEpoch() external view returns (uint256);
function getEpochProcessingState()
external
view
returns (uint256, uint256, uint256, uint256, uint256);
function systemAlreadyInitialized() external view returns (bool);
function isBlocked() external view returns (bool);
function isTimeForNextEpoch() external view returns (bool);
function isOnEpochProcess() external view returns (bool);
function getFirstBlockAtEpoch(uint256) external view returns (uint256);
function getLastBlockAtEpoch(uint256) external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface ICeloVersionedContract {
/**
* @notice Returns the storage, major, minor, and patch version of the contract.
* @return Storage version of the contract.
* @return Major version of the contract.
* @return Minor version of the contract.
* @return Patch version of the contract.
*/
function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface ICeloUnreleasedTreasury {
/**
* @notice Releases the Celo to the specified address.
* @param to The address to release the amount to.
* @param amount The amount to release.
*/
function release(address to, uint256 amount) external;
function getRemainingBalanceToRelease() external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IAccounts {
function setAccountDataEncryptionKey(bytes calldata) external;
function setMetadataURL(string calldata) external;
function setName(string calldata) external;
function setWalletAddress(address, uint8, bytes32, bytes32) external;
function setAccount(string calldata, bytes calldata, address, uint8, bytes32, bytes32) external;
function authorizeVoteSigner(address, uint8, bytes32, bytes32) external;
function authorizeValidatorSigner(address, uint8, bytes32, bytes32) external;
function authorizeValidatorSignerWithPublicKey(
address,
uint8,
bytes32,
bytes32,
bytes calldata
) external;
function authorizeValidatorSignerWithKeys(
address,
uint8,
bytes32,
bytes32,
bytes calldata,
bytes calldata,
bytes calldata
) external;
function authorizeAttestationSigner(address, uint8, bytes32, bytes32) external;
function setEip712DomainSeparator() external;
function createAccount() external returns (bool);
function setPaymentDelegation(address, uint256) external;
function isAccount(address) external view returns (bool);
function voteSignerToAccount(address) external view returns (address);
function validatorSignerToAccount(address) external view returns (address);
function attestationSignerToAccount(address) external view returns (address);
function signerToAccount(address) external view returns (address);
function getAttestationSigner(address) external view returns (address);
function getValidatorSigner(address) external view returns (address);
function getVoteSigner(address) external view returns (address);
function hasAuthorizedVoteSigner(address) external view returns (bool);
function hasAuthorizedValidatorSigner(address) external view returns (bool);
function hasAuthorizedAttestationSigner(address) external view returns (bool);
function batchGetMetadataURL(
address[] calldata
) external view returns (uint256[] memory, bytes memory);
function getDataEncryptionKey(address) external view returns (bytes memory);
function getWalletAddress(address) external view returns (address);
function getMetadataURL(address) external view returns (string memory);
function getName(address) external view returns (string memory);
function getPaymentDelegation(address) external view returns (address, uint256);
function isSigner(address, address, bytes32) external view returns (bool);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
/**
* @title Used with proxied contracts that have an `initialize` function.
* @notice Ensures the `initialize` function:
* - gets called only once
* - cannot be called on the logic contract.
*/
contract Initializable {
bool public initialized;
/**
* @notice Ensures the initializer function cannot be called more than once.
*/
modifier initializer() {
require(!initialized, "contract already initialized");
initialized = true;
_;
}
/**
* @notice By default, ensures that the `initialize` function cannot be called
* on the logic contract.
* @param testingDeployment When set to true, allows the `initialize` function
* to be called, which is useful in testing when not setting up with a Proxy.
*/
constructor(bool testingDeployment) public {
if (!testingDeployment) {
initialized = true;
}
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
/**
* @title FixidityLib
* @author Gadi Guy, Alberto Cuesta Canada
* @notice This library provides fixed point arithmetic with protection against
* overflow.
* All operations are done with uint256 and the operands must have been created
* with any of the newFrom* functions, which shift the comma digits() to the
* right and check for limits, or with wrap() which expects a number already
* in the internal representation of a fraction.
* When using this library be sure to use maxNewFixed() as the upper limit for
* creation of fixed point numbers.
* @dev All contained functions are pure and thus marked internal to be inlined
* on consuming contracts at compile time for gas efficiency.
*/
library FixidityLib {
struct Fraction {
uint256 value;
}
uint256 private constant FIXED1_UINT = 1000000000000000000000000;
/**
* @notice Number of positions that the comma is shifted to the right.
*/
function digits() internal pure returns (uint8) {
return 24;
}
/**
* @notice This is 1 in the fixed point units used in this library.
* @dev Test fixed1() equals 10^digits()
* Hardcoded to 24 digits.
*/
function fixed1() internal pure returns (Fraction memory) {
return Fraction(FIXED1_UINT);
}
/**
* @notice Wrap a uint256 that represents a 24-decimal fraction in a Fraction
* struct.
* @param x Number that already represents a 24-decimal fraction.
* @return A Fraction struct with contents x.
*/
function wrap(uint256 x) internal pure returns (Fraction memory) {
return Fraction(x);
}
/**
* @notice Unwraps the uint256 inside of a Fraction struct.
*/
function unwrap(Fraction memory x) internal pure returns (uint256) {
return x.value;
}
/**
* @notice The amount of decimals lost on each multiplication operand.
* @dev Test mulPrecision() equals sqrt(fixed1)
*/
function mulPrecision() internal pure returns (uint256) {
return 1000000000000;
}
/**
* @notice Maximum value that can be converted to fixed point. Optimize for deployment.
* @dev
* Test maxNewFixed() equals maxUint256() / fixed1()
*/
function maxNewFixed() internal pure returns (uint256) {
return 115792089237316195423570985008687907853269984665640564;
}
/**
* @notice Converts a uint256 to fixed point Fraction
* @dev Test newFixed(0) returns 0
* Test newFixed(1) returns fixed1()
* Test newFixed(maxNewFixed()) returns maxNewFixed() * fixed1()
* Test newFixed(maxNewFixed()+1) fails
*/
function newFixed(uint256 x) internal pure returns (Fraction memory) {
require(x <= maxNewFixed(), "can't create fixidity number larger than maxNewFixed()");
return Fraction(x * FIXED1_UINT);
}
/**
* @notice Converts a uint256 in the fixed point representation of this
* library to a non decimal. All decimal digits will be truncated.
*/
function fromFixed(Fraction memory x) internal pure returns (uint256) {
return x.value / FIXED1_UINT;
}
/**
* @notice Converts two uint256 representing a fraction to fixed point units,
* equivalent to multiplying dividend and divisor by 10^digits().
* @param numerator numerator must be <= maxNewFixed()
* @param denominator denominator must be <= maxNewFixed() and denominator can't be 0
* @dev
* Test newFixedFraction(1,0) fails
* Test newFixedFraction(0,1) returns 0
* Test newFixedFraction(1,1) returns fixed1()
* Test newFixedFraction(1,fixed1()) returns 1
*/
function newFixedFraction(
uint256 numerator,
uint256 denominator
) internal pure returns (Fraction memory) {
Fraction memory convertedNumerator = newFixed(numerator);
Fraction memory convertedDenominator = newFixed(denominator);
return divide(convertedNumerator, convertedDenominator);
}
/**
* @notice Returns the integer part of a fixed point number.
* @dev
* Test integer(0) returns 0
* Test integer(fixed1()) returns fixed1()
* Test integer(newFixed(maxNewFixed())) returns maxNewFixed()*fixed1()
*/
function integer(Fraction memory x) internal pure returns (Fraction memory) {
return Fraction((x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow
}
/**
* @notice Returns the fractional part of a fixed point number.
* In the case of a negative number the fractional is also negative.
* @dev
* Test fractional(0) returns 0
* Test fractional(fixed1()) returns 0
* Test fractional(fixed1()-1) returns 10^24-1
*/
function fractional(Fraction memory x) internal pure returns (Fraction memory) {
return Fraction(x.value - (x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow
}
/**
* @notice x+y.
* @dev The maximum value that can be safely used as an addition operator is defined as
* maxFixedAdd = maxUint256()-1 / 2, or
* 57896044618658097711785492504343953926634992332820282019728792003956564819967.
* Test add(maxFixedAdd,maxFixedAdd) equals maxFixedAdd + maxFixedAdd
* Test add(maxFixedAdd+1,maxFixedAdd+1) throws
*/
function add(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
uint256 z = x.value + y.value;
require(z >= x.value, "add overflow detected");
return Fraction(z);
}
/**
* @notice x-y.
* @dev
* Test subtract(6, 10) fails
*/
function subtract(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
require(x.value >= y.value, "substraction underflow detected");
return Fraction(x.value - y.value);
}
/**
* @notice x*y. If any of the operators is higher than the max multiplier value it
* might overflow.
* @dev The maximum value that can be safely used as a multiplication operator
* (maxFixedMul) is calculated as sqrt(maxUint256()*fixed1()),
* or 340282366920938463463374607431768211455999999999999
* Test multiply(0,0) returns 0
* Test multiply(maxFixedMul,0) returns 0
* Test multiply(0,maxFixedMul) returns 0
* Test multiply(fixed1()/mulPrecision(),fixed1()*mulPrecision()) returns fixed1()
* Test multiply(maxFixedMul,maxFixedMul) is around maxUint256()
* Test multiply(maxFixedMul+1,maxFixedMul+1) fails
*/
function multiply(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
if (x.value == 0 || y.value == 0) return Fraction(0);
if (y.value == FIXED1_UINT) return x;
if (x.value == FIXED1_UINT) return y;
// Separate into integer and fractional parts
// x = x1 + x2, y = y1 + y2
uint256 x1 = integer(x).value / FIXED1_UINT;
uint256 x2 = fractional(x).value;
uint256 y1 = integer(y).value / FIXED1_UINT;
uint256 y2 = fractional(y).value;
// (x1 + x2) * (y1 + y2) = (x1 * y1) + (x1 * y2) + (x2 * y1) + (x2 * y2)
uint256 x1y1 = x1 * y1;
if (x1 != 0) require(x1y1 / x1 == y1, "overflow x1y1 detected");
// x1y1 needs to be multiplied back by fixed1
// solium-disable-next-line mixedcase
uint256 fixed_x1y1 = x1y1 * FIXED1_UINT;
if (x1y1 != 0) require(fixed_x1y1 / x1y1 == FIXED1_UINT, "overflow x1y1 * fixed1 detected");
x1y1 = fixed_x1y1;
uint256 x2y1 = x2 * y1;
if (x2 != 0) require(x2y1 / x2 == y1, "overflow x2y1 detected");
uint256 x1y2 = x1 * y2;
if (x1 != 0) require(x1y2 / x1 == y2, "overflow x1y2 detected");
x2 = x2 / mulPrecision();
y2 = y2 / mulPrecision();
uint256 x2y2 = x2 * y2;
if (x2 != 0) require(x2y2 / x2 == y2, "overflow x2y2 detected");
// result = fixed1() * x1 * y1 + x1 * y2 + x2 * y1 + x2 * y2 / fixed1();
Fraction memory result = Fraction(x1y1);
result = add(result, Fraction(x2y1)); // Add checks for overflow
result = add(result, Fraction(x1y2)); // Add checks for overflow
result = add(result, Fraction(x2y2)); // Add checks for overflow
return result;
}
/**
* @notice 1/x
* @dev
* Test reciprocal(0) fails
* Test reciprocal(fixed1()) returns fixed1()
* Test reciprocal(fixed1()*fixed1()) returns 1 // Testing how the fractional is truncated
* Test reciprocal(1+fixed1()*fixed1()) returns 0 // Testing how the fractional is truncated
* Test reciprocal(newFixedFraction(1, 1e24)) returns newFixed(1e24)
*/
function reciprocal(Fraction memory x) internal pure returns (Fraction memory) {
require(x.value != 0, "can't call reciprocal(0)");
return Fraction((FIXED1_UINT * FIXED1_UINT) / x.value); // Can't overflow
}
/**
* @notice x/y. If the dividend is higher than the max dividend value, it
* might overflow. You can use multiply(x,reciprocal(y)) instead.
* @dev The maximum value that can be safely used as a dividend (maxNewFixed) is defined as
* divide(maxNewFixed,newFixedFraction(1,fixed1())) is around maxUint256().
* This yields the value 115792089237316195423570985008687907853269984665640564.
* Test maxNewFixed equals maxUint256()/fixed1()
* Test divide(maxNewFixed,1) equals maxNewFixed*(fixed1)
* Test divide(maxNewFixed+1,multiply(mulPrecision(),mulPrecision())) throws
* Test divide(fixed1(),0) fails
* Test divide(maxNewFixed,1) = maxNewFixed*(10^digits())
* Test divide(maxNewFixed+1,1) throws
*/
function divide(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
require(y.value != 0, "can't divide by 0");
uint256 X = x.value * FIXED1_UINT;
require(X / FIXED1_UINT == x.value, "overflow at divide");
return Fraction(X / y.value);
}
/**
* @notice x > y
*/
function gt(Fraction memory x, Fraction memory y) internal pure returns (bool) {
return x.value > y.value;
}
/**
* @notice x >= y
*/
function gte(Fraction memory x, Fraction memory y) internal pure returns (bool) {
return x.value >= y.value;
}
/**
* @notice x < y
*/
function lt(Fraction memory x, Fraction memory y) internal pure returns (bool) {
return x.value < y.value;
}
/**
* @notice x <= y
*/
function lte(Fraction memory x, Fraction memory y) internal pure returns (bool) {
return x.value <= y.value;
}
/**
* @notice x == y
*/
function equals(Fraction memory x, Fraction memory y) internal pure returns (bool) {
return x.value == y.value;
}
/**
* @notice x <= 1
*/
function isProperFraction(Fraction memory x) internal pure returns (bool) {
return lte(x, fixed1());
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.7 <0.8.20;
interface IScoreReader {
function getValidatorScore(address validator) external view returns (uint256);
function getGroupScore(address validator) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.13 <0.9.0;
/// Possibly not final version
interface IOracle {
function getExchangeRate(
address token
) external view returns (uint256 numerator, uint256 denominator);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IEpochManagerInitializer {
function initialize(address registryAddress, uint256 newEpochDuration) external;
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0 <0.8.20;
// Note: This is not an exact copy of UsingRegistry or UsingRegistryV2 in the contract's folder
// because Mento's interfaces still don't support Solidity 0.8
import "@openzeppelin/contracts8/access/Ownable.sol";
import "@openzeppelin/contracts8/token/ERC20/IERC20.sol";
import "../../contracts/common/interfaces/IRegistry.sol";
import "../../contracts/common/interfaces/IAccounts.sol";
import "../../contracts/common/interfaces/IEpochManager.sol";
import "../../contracts/common/interfaces/IFreezer.sol";
import "../../contracts/common/interfaces/ICeloUnreleasedTreasury.sol";
import "../../contracts/common/interfaces/IFeeCurrencyWhitelist.sol";
import "../../contracts/common/interfaces/IFeeHandlerSeller.sol";
import "../../contracts/common/interfaces/IEpochManager.sol";
import "../../contracts/governance/interfaces/IGovernance.sol";
import "../../contracts/governance/interfaces/ILockedGold.sol";
import "../../contracts/governance/interfaces/ILockedCelo.sol";
import "../../contracts/governance/interfaces/IValidators.sol";
import "../../contracts/governance/interfaces/IElection.sol";
import "../../contracts/governance/interfaces/IEpochRewards.sol";
import "../../contracts/stability/interfaces/ISortedOracles.sol";
import "./interfaces/IScoreReader.sol";
contract UsingRegistry is Ownable {
// solhint-disable state-visibility
bytes32 constant ACCOUNTS_REGISTRY_ID = keccak256(abi.encodePacked("Accounts"));
bytes32 constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked("Attestations"));
bytes32 constant DOWNTIME_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DowntimeSlasher"));
bytes32 constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID =
keccak256(abi.encodePacked("DoubleSigningSlasher"));
bytes32 constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked("Election"));
bytes32 constant EPOCH_REWARDS_REGISTRY_ID = keccak256(abi.encodePacked("EpochRewards"));
bytes32 constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked("Exchange"));
bytes32 constant FEE_CURRENCY_WHITELIST_REGISTRY_ID =
keccak256(abi.encodePacked("FeeCurrencyWhitelist"));
bytes32 constant FREEZER_REGISTRY_ID = keccak256(abi.encodePacked("Freezer"));
bytes32 constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("GoldToken"));
bytes32 constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked("Governance"));
bytes32 constant GOVERNANCE_SLASHER_REGISTRY_ID =
keccak256(abi.encodePacked("GovernanceSlasher"));
bytes32 constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked("LockedGold"));
bytes32 constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked("Reserve"));
bytes32 constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked("Random"));
bytes32 constant SORTED_ORACLES_REGISTRY_ID = keccak256(abi.encodePacked("SortedOracles"));
bytes32 constant STABLE_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("StableToken"));
bytes32 constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked("Validators"));
bytes32 constant MENTOFEEHANDLERSELLER_REGISTRY_ID =
keccak256(abi.encodePacked("MentoFeeHandlerSeller"));
bytes32 constant CELO_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("CeloToken"));
bytes32 constant LOCKED_CELO_REGISTRY_ID = keccak256(abi.encodePacked("LockedCelo"));
bytes32 constant CELO_UNRELEASED_TREASURY_REGISTRY_ID =
keccak256(abi.encodePacked("CeloUnreleasedTreasury"));
bytes32 constant EPOCH_MANAGER_ENABLER_REGISTRY_ID =
keccak256(abi.encodePacked("EpochManagerEnabler"));
bytes32 constant EPOCH_MANAGER_REGISTRY_ID = keccak256(abi.encodePacked("EpochManager"));
bytes32 constant SCORE_MANAGER_REGISTRY_ID = keccak256(abi.encodePacked("ScoreManager"));
// solhint-enable state-visibility
IRegistry public registry;
event RegistrySet(address indexed registryAddress);
modifier onlyRegisteredContract(bytes32 identifierHash) {
require(registry.getAddressForOrDie(identifierHash) == msg.sender, "only registered contract");
_;
}
modifier onlyRegisteredContracts(bytes32[] memory identifierHashes) {
require(registry.isOneOf(identifierHashes, msg.sender), "only registered contracts");
_;
}
/**
* @notice Updates the address pointing to a Registry contract.
* @param registryAddress The address of a registry contract for routing to other contracts.
*/
function setRegistry(address registryAddress) public onlyOwner {
require(registryAddress != address(0), "Cannot register the null address");
registry = IRegistry(registryAddress);
emit RegistrySet(registryAddress);
}
function getGoldToken() internal view returns (IERC20) {
return IERC20(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID));
}
function getCeloToken() internal view returns (IERC20) {
return IERC20(registry.getAddressForOrDie(CELO_TOKEN_REGISTRY_ID));
}
function getFreezer() internal view returns (IFreezer) {
return IFreezer(registry.getAddressForOrDie(FREEZER_REGISTRY_ID));
}
function getSortedOracles() internal view returns (ISortedOracles) {
return ISortedOracles(registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID));
}
function getFeeCurrencyWhitelist() internal view returns (IFeeCurrencyWhitelist) {
return IFeeCurrencyWhitelist(registry.getAddressForOrDie(FEE_CURRENCY_WHITELIST_REGISTRY_ID));
}
function getLockedGold() internal view returns (ILockedGold) {
return ILockedGold(registry.getAddressForOrDie(LOCKED_GOLD_REGISTRY_ID));
}
function getLockedCelo() internal view returns (ILockedCelo) {
return ILockedCelo(registry.getAddressForOrDie(LOCKED_CELO_REGISTRY_ID));
}
// Current version of Mento doesn't support 0.8
function getStableToken() internal view returns (address) {
return registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID);
}
function getMentoFeeHandlerSeller() internal view returns (IFeeHandlerSeller) {
return IFeeHandlerSeller(registry.getAddressForOrDie(MENTOFEEHANDLERSELLER_REGISTRY_ID));
}
function getAccounts() internal view returns (IAccounts) {
return IAccounts(registry.getAddressForOrDie(ACCOUNTS_REGISTRY_ID));
}
function getValidators() internal view returns (IValidators) {
return IValidators(registry.getAddressForOrDie(VALIDATORS_REGISTRY_ID));
}
function getElection() internal view returns (IElection) {
return IElection(registry.getAddressForOrDie(ELECTION_REGISTRY_ID));
}
function getEpochRewards() internal view returns (IEpochRewards) {
return IEpochRewards(registry.getAddressForOrDie(EPOCH_REWARDS_REGISTRY_ID));
}
function getGovernance() internal view returns (IGovernance) {
return IGovernance(registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID));
}
function getCeloUnreleasedTreasury() internal view returns (ICeloUnreleasedTreasury) {
return
ICeloUnreleasedTreasury(registry.getAddressForOrDie(CELO_UNRELEASED_TREASURY_REGISTRY_ID));
}
function getEpochManager() internal view returns (IEpochManager) {
return IEpochManager(registry.getAddressForOrDie(EPOCH_MANAGER_REGISTRY_ID));
}
function getScoreReader() internal view returns (IScoreReader) {
return IScoreReader(registry.getAddressForOrDie(SCORE_MANAGER_REGISTRY_ID));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @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 Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.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.
*
* By default, the owner account will be the one that deploys the contract. 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 Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @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) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @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 {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}{
"remappings": [],
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "paris",
"libraries": {},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"bool","name":"test","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"newEpochDuration","type":"uint256"}],"name":"EpochDurationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"epochNumber","type":"uint256"}],"name":"EpochProcessingEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"epochNumber","type":"uint256"}],"name":"EpochProcessingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"group","type":"address"},{"indexed":true,"internalType":"uint256","name":"epochNumber","type":"uint256"}],"name":"GroupMarkedForProcessing","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"group","type":"address"},{"indexed":true,"internalType":"uint256","name":"epochNumber","type":"uint256"}],"name":"GroupProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOracleAddress","type":"address"}],"name":"OracleAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registryAddress","type":"address"}],"name":"RegistrySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"validator","type":"address"},{"indexed":false,"internalType":"uint256","name":"validatorPayment","type":"uint256"},{"indexed":true,"internalType":"address","name":"group","type":"address"},{"indexed":false,"internalType":"uint256","name":"groupPayment","type":"uint256"},{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"delegatedPayment","type":"uint256"}],"name":"ValidatorEpochPaymentDistributed","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"electedAccounts","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"electedSigners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochProcessing","outputs":[{"internalType":"enum EpochManager.EpochProcessStatus","name":"status","type":"uint8"},{"internalType":"uint256","name":"perValidatorReward","type":"uint256"},{"internalType":"uint256","name":"totalRewardsVoter","type":"uint256"},{"internalType":"uint256","name":"totalRewardsCommunity","type":"uint256"},{"internalType":"uint256","name":"totalRewardsCarbonFund","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"groups","type":"address[]"},{"internalType":"address[]","name":"lessers","type":"address[]"},{"internalType":"address[]","name":"greaters","type":"address[]"}],"name":"finishNextEpochProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"firstKnownEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentEpochNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getElectedAccountByIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getElectedAccounts","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getElectedSignerByIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getElectedSigners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"getEpochByBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochNumber","type":"uint256"}],"name":"getEpochByNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"getEpochNumberOfBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEpochProcessingState","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"getFirstBlockAtEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"getLastBlockAtEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVersionNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"registryAddress","type":"address"},{"internalType":"uint256","name":"newEpochDuration","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"firstEpochNumber","type":"uint256"},{"internalType":"uint256","name":"firstEpochBlock","type":"uint256"},{"internalType":"address[]","name":"firstElected","type":"address[]"}],"name":"initializeSystem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBlocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isEpochProcessingStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isIndividualProcessing","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isOnEpochProcess","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSystemInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTimeForNextEpoch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numberOfElectedInCurrentSet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"group","type":"address"},{"internalType":"address","name":"lesser","type":"address"},{"internalType":"address","name":"greater","type":"address"}],"name":"processGroup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"groups","type":"address[]"},{"internalType":"address[]","name":"lessers","type":"address[]"},{"internalType":"address[]","name":"greaters","type":"address[]"}],"name":"processGroups","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"processedGroups","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"validator","type":"address"}],"name":"sendValidatorPayment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newEpochDuration","type":"uint256"}],"name":"setEpochDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOracleAddress","type":"address"}],"name":"setOracleAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registryAddress","type":"address"}],"name":"setRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setToProcessGroups","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startNextEpochProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"systemAlreadyInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toProcessGroups","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"validatorPendingPayments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405260006012553480156200001657600080fd5b50604051620045fa380380620045fa8339810160408190526200003991620000bf565b80806200004e576000805460ff191660011790555b506200005a3362000066565b506001600255620000ea565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b600060208284031215620000d257600080fd5b81518015158114620000e357600080fd5b9392505050565b61450080620000fa6000396000f3fe608060405234801561001057600080fd5b506004361061028a5760003560e01c80638657f6151161015c578063b5a842cd116100ce578063d75f0da711610087578063d75f0da71461056e578063ebf52c5114610576578063ef0551d1146105a6578063f1542de5146105b9578063f1fcbab1146105cc578063f2fde38b146105d557600080fd5b8063b5a842cd14610528578063b97dd9e21461053b578063ba18ee4d14610543578063bd5a0a351461054b578063cd6dc68714610553578063d02cfcf31461056657600080fd5b806398f6c7601161012057806398f6c760146104ca5780639b217558146104ea5780639f3bf7a0146104f2578063a0fa0d56146104fa578063a89ae4ba14610502578063a91ee0dc1461051557600080fd5b80638657f61514610457578063891c48fb1461046a5780638c25656e146104735780638da5cb5b1461048657806398b509051461049c57600080fd5b806351ccd8f01161020057806364c2c255116101b957806364c2c255146103f4578063653c356f14610401578063667f331b146104145780636857f6a114610427578063715018a61461043c5780637b1039991461044457600080fd5b806351ccd8f01461038457806352ba62621461039757806354255be0146103aa57806354454b48146103d15780635915e077146103d9578063639a84d3146103ec57600080fd5b80633a65c499116102525780633a65c499146103325780633b1eb4bf146103455780634406d661146103585780634408d2ba146103605780634c69c00f146103685780634ff0876a1461037b57600080fd5b8063158ef93e1461028f578063186b978d146102b1578063210b315b146102df5780632ba47274146102f457806330024dfe1461031f575b600080fd5b60005461029c9060ff1681565b60405190151581526020015b60405180910390f35b6102d16102bf366004613d6e565b60096020526000908152604090205481565b6040519081526020016102a8565b6102f26102ed366004613d92565b6105e8565b005b610307610302366004613ddd565b6107e4565b6040516001600160a01b0390911681526020016102a8565b6102f261032d366004613ddd565b610838565b610307610340366004613ddd565b610946565b6102d1610353366004613ddd565b610970565b61029c6109ad565b6102d16109ca565b6102f2610376366004613d6e565b6109f7565b6102d160045481565b6102f2610392366004613e61565b610b8a565b6102f26103a5366004613f61565b611066565b6001806000805b6040805194855260208501939093529183015260608201526080016102a8565b61029c611104565b6102f26103e7366004613d6e565b611126565b6102d1611663565b60035461029c9060ff1681565b6103b161040f366004613ddd565b611690565b6102f2610422366004613f61565b6116dd565b61042f611d00565b6040516102a89190613ffb565b6102f2611d86565b600154610307906001600160a01b031681565b610307610465366004613ddd565b611d9a565b6102d160055481565b610307610481366004613ddd565b611dd3565b60005461010090046001600160a01b0316610307565b600a54600b54600c54600d54600e546104b99460ff169392919085565b6040516102a895949392919061405e565b6102d16104d8366004613d6e565b60106020526000908152604090205481565b61029c611de3565b6102f2611dfb565b61029c612084565b600754610307906001600160a01b031681565b6102f2610523366004613d6e565b6120af565b6102d1610536366004613ddd565b612157565b6103b16121fd565b61029c612240565b61042f612249565b6102f26105613660046140a1565b6122cd565b6102f26123f4565b61029c6126df565b61057e6126e9565b604080519586526020860194909452928401919091526060830152608082015260a0016102a8565b6102d16105b4366004613ddd565b612732565b6103b16105c7366004613ddd565b6127d5565b6102d160125481565b6102f26105e3366004613d6e565b61284d565b600a6105f2611104565b6106535760405162461bcd60e51b815260206004820152602760248201527f496e646976756475616c2065706f63682070726f63657373206973206e6f74206044820152661cdd185c9d195960ca1b60648201526084015b60405180910390fd5b6000601254116106a55760405162461bcd60e51b815260206004820152601960248201527f6e6f206d6f72652067726f75707320746f2070726f6365737300000000000000604482015260640161064a565b6001600160a01b038416600090815260096020526040902054806106db5760405162461bcd60e51b815260040161064a906140cd565b60006106e56128c6565b90506000198214610763576040516312541a6b60e01b81526001600160a01b03878116600483015260248201849052868116604483015285811660648301528216906312541a6b90608401600060405180830381600087803b15801561074a57600080fd5b505af115801561075e573d6000803e3d6000fd5b505050505b6001600160a01b0386166000908152600960205260408120819055601280549161078c83614125565b90915550506006546040516001600160a01b038816907f15ff42ed3ffc7d45600460c399f3a885b3c25e0c4f613266e5fbd5dc80ea14c790600090a36012546000036107dc576107dc8382612969565b505050505050565b60006107ee611de3565b61080a5760405162461bcd60e51b815260040161064a9061413c565b6011828154811061081d5761081d614173565b6000918252602090912001546001600160a01b031692915050565b610840612cb1565b600081116108a65760405162461bcd60e51b815260206004820152602d60248201527f4e65772065706f6368206475726174696f6e206d75737420626520677265617460448201526c32b9103a3430b7103d32b9379760991b606482015260840161064a565b6108ae612240565b156109135760405162461bcd60e51b815260206004820152602f60248201527f43616e6e6f74206368616e67652065706f6368206475726174696f6e2064757260448201526e34b73390383937b1b2b9b9b4b7339760891b606482015260840161064a565b600481905560405181907fe018a3a09e27f3987d8cbe7e32e55899996a50099fb79f333c0030831842eeb090600090a250565b6011818154811061095657600080fd5b6000918252602090912001546001600160a01b0316905081565b600061097a611de3565b6109965760405162461bcd60e51b815260040161064a9061413c565b60006109a183612d11565b50929695505050505050565b60006109b7612240565b806109c557506109c5611104565b905090565b60006109d4611de3565b6109f05760405162461bcd60e51b815260040161064a9061413c565b5060065490565b6109ff612cb1565b6001600160a01b038116610a645760405162461bcd60e51b815260206004820152602660248201527f43616e6e6f74207365742061646472657373207a65726f20617320746865204f6044820152653930b1b6329760d11b606482015260840161064a565b6007546001600160a01b0390811690821603610acd5760405162461bcd60e51b815260206004820152602260248201527f4f7261636c6520616464726573732063616e6e6f74206265207468652073616d604482015261329760f11b606482015260840161064a565b610ad5612240565b15610b405760405162461bcd60e51b815260206004820152603560248201527f43616e6e6f74206368616e6765206f7261636c6520616464726573732064757260448201527434b7339032b837b1b410383937b1b2b9b9b4b7339760591b606482015260840161064a565b600780546001600160a01b0319166001600160a01b0383169081179091556040517fdd82bdfc28fcc826c53263dc2a2b6083e27e92699ebfee617227e08e21c202f090600090a250565b6001546040517222b837b1b426b0b730b3b2b922b730b13632b960691b60208201526001600160a01b039091169063dcf0aaed90603301604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610bf591815260200190565b602060405180830381865afa158015610c12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c369190614189565b6001600160a01b0316336001600160a01b031614610c965760405162461bcd60e51b815260206004820152601960248201527f6d73672e73656e646572206973206e6f7420456e61626c657200000000000000604482015260640161064a565b6000610ca0612fa9565b6001546040517543656c6f556e72656c6561736564547265617375727960501b60208201526001600160a01b03928316926370a0823192169063dcf0aaed90603601604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610d1691815260200190565b602060405180830381865afa158015610d33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d579190614189565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610d9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbf91906141a6565b11610e1b5760405162461bcd60e51b815260206004820152602660248201527f43656c6f556e72656c65617365645472656173757279206e6f742079657420666044820152653ab73232b21760d11b606482015260840161064a565b610e23611de3565b15610e705760405162461bcd60e51b815260206004820181905260248201527f45706f63682073797374656d20616c726561647920696e697469616c697a6564604482015260640161064a565b60008311610ed25760405162461bcd60e51b815260206004820152602960248201527f46697273742065706f6368206e756d626572206d75737420626520677265617460448201526806572207468616e20360bc1b606482015260840161064a565b60008211610f335760405162461bcd60e51b815260206004820152602860248201527f46697273742065706f636820626c6f636b206d75737420626520677265617465604482015267072207468616e20360c41b606482015260840161064a565b43821115610fa95760405162461bcd60e51b815260206004820152603a60248201527f46697273742065706f636820626c6f636b206d757374206265206c657373206f60448201527f7220657175616c207468616e2063757272656e7420626c6f636b000000000000606482015260840161064a565b60008151116110125760405162461bcd60e51b815260206004820152602f60248201527f466972737420656c65637465642076616c696461746f7273206d75737420626560448201526e02067726561746572207468616e203608c1b606482015260840161064a565b6003805460ff19166001179055600583905560068390556000838152600f602090815260409091208381554260028201558251909161105691600891850190613cdf565b5061106082612fdc565b50505050565b60005b858110156110fb576110e987878381811061108657611086614173565b905060200201602081019061109b9190613d6e565b8686848181106110ad576110ad614173565b90506020020160208101906110c29190613d6e565b8585858181106110d4576110d4614173565b90506020020160208101906102ed9190613d6e565b806110f3816141bf565b915050611069565b50505050505050565b600060025b600a5460ff16600281111561112057611120614048565b14905090565b61112e611de3565b61114a5760405162461bcd60e51b815260040161064a9061413c565b6001600160a01b03811660009081526010602052604081205461116c90613190565b6001600160a01b038316600090815260106020526040812081905590915061119261324e565b60405163bb0f1fa560e01b81526001600160a01b03858116600483015291925060009183169063bb0f1fa590602401602060405180830381865afa1580156111de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112029190614189565b604051639b9d516160e01b81526001600160a01b038083166004830152919250600091841690639b9d516190602401600060405180830381865afa15801561124e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112769190810190614247565b505050505091505060006112b46112af6112a88460408051602080820183526000909152815190810190915290815290565b8790613282565b6135f3565b905060006112d4826112c5886135f3565b6112cf9190614332565b613190565b90506000806112e161360d565b604051639f024f4b60e01b81526001600160a01b038b811660048301529190911690639f024f4b906024016040805180830381865afa158015611328573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134c9190614345565b9150915060006113816112af61137a8460408051602080820183526000909152815190810190915290815290565b8690613282565b905060008161138f866135f3565b6113999190614332565b905060006113a561363f565b9050811561146c5760405163a9059cbb60e01b81526001600160a01b038d811660048301526024820184905282169063a9059cbb906044016020604051808303816000875af11580156113fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114209190614373565b61146c5760405162461bcd60e51b815260206004820152601c60248201527f7472616e73666572206661696c656420746f2076616c696461746f7200000000604482015260640161064a565b861561153c5760405163a9059cbb60e01b81526001600160a01b038a811660048301526024820189905282169063a9059cbb906044016020604051808303816000875af11580156114c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e59190614373565b61153c5760405162461bcd60e51b815260206004820152602260248201527f7472616e73666572206661696c656420746f2076616c696461746f722067726f604482015261075760f41b606482015260840161064a565b82156116015760405163a9059cbb60e01b81526001600160a01b0386811660048301526024820185905282169063a9059cbb906044016020604051808303816000875af1158015611591573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b59190614373565b6116015760405162461bcd60e51b815260206004820152601c60248201527f7472616e73666572206661696c656420746f2064656c65676174656500000000604482015260640161064a565b60408051838152602081018990529081018490526001600160a01b03808716918b8216918f16907fee2788e7abedfc61d9608e143b172de1a608a4298b06ed8c84838aa0ad6bd1369060600160405180910390a4505050505050505050505050565b600061166d611de3565b6116895760405162461bcd60e51b815260040161064a9061413c565b5060085490565b60008060008061169e611de3565b6116ba5760405162461bcd60e51b815260040161064a9061413c565b6000806000806116c989612d11565b929d919c509a509098509650505050505050565b6116e5613674565b6116ed612240565b6117395760405162461bcd60e51b815260206004820152601c60248201527f45706f63682070726f63657373206973206e6f74207374617274656400000000604482015260640161064a565b601254156117af5760405162461bcd60e51b815260206004820152603e60248201527f43616e27742066696e6973682065706f6368207768696c6520696e646976696460448201527f75616c2067726f75707320617265206265696e672070726f6365737365640000606482015260840161064a565b600a6000806117bc61324e565b905060006117c86128c6565b905060006117d46136cb565b601154600854919250146117fa5760405162461bcd60e51b815260040161064a90614395565b60005b600854811015611a5a576000846001600160a01b031663bb0f1fa56008848154811061182b5761182b614173565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa15801561187b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189f9190614189565b6001600160a01b038116600090815260096020526040812054919250036119ee57856118ca816141bf565b6040516310e0415560e11b81526001600160a01b03848116600483015291985060009250908516906321c082aa90602401602060405180830381865afa158015611918573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193c91906141a6565b6002890154604051622400b960e71b81526001600160a01b038581166004830152602482019290925260448101839052919250600091908716906312005c8090606401602060405180830381865afa15801561199c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c091906141a6565b905080156119ce57806119d2565b6000195b6001600160a01b03841660009081526009602052604090205550505b60088281548110611a0157611a01614173565b600091825260209091200180546001600160a01b03191690556011805483908110611a2e57611a2e614173565b600091825260209091200180546001600160a01b03191690555080611a52816141bf565b9150506117fd565b50838a14611aaa5760405162461bcd60e51b815260206004820152601f60248201527f6e756d626572206f662067726f75707320646f6573206e6f74206d6174636800604482015260640161064a565b60005b8a811015611ce6576000600960008e8e85818110611acd57611acd614173565b9050602002016020810190611ae29190613d6e565b6001600160a01b03166001600160a01b0316815260200190815260200160002054905060008111611b255760405162461bcd60e51b815260040161064a906140cd565b6000198114611c2557836001600160a01b03166312541a6b8e8e85818110611b4f57611b4f614173565b9050602002016020810190611b649190613d6e565b838e8e87818110611b7757611b77614173565b9050602002016020810190611b8c9190613d6e565b8d8d88818110611b9e57611b9e614173565b9050602002016020810190611bb39190613d6e565b60405160e086901b6001600160e01b03191681526001600160a01b039485166004820152602481019390935290831660448301529091166064820152608401600060405180830381600087803b158015611c0c57600080fd5b505af1158015611c20573d6000803e3d6000fd5b505050505b600960008e8e85818110611c3b57611c3b614173565b9050602002016020810190611c509190613d6e565b6001600160a01b03166001600160a01b03168152602001908152602001600020600090556006548d8d84818110611c8957611c89614173565b9050602002016020810190611c9e9190613d6e565b6001600160a01b03167f15ff42ed3ffc7d45600460c399f3a885b3c25e0c4f613266e5fbd5dc80ea14c760405160405180910390a35080611cde816141bf565b915050611aad565b50611cf18583612969565b50505050506107dc6001600255565b6060611d0a611de3565b611d265760405162461bcd60e51b815260040161064a9061413c565b6008805480602002602001604051908101604052809291908181526020018280548015611d7c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611d5e575b5050505050905090565b611d8e612cb1565b611d986000613701565b565b6000611da4611de3565b611dc05760405162461bcd60e51b815260040161064a9061413c565b6008828154811061081d5761081d614173565b6008818154811061095657600080fd5b6000805460ff1680156109c557505060035460ff1690565b611e03613674565b611e0b611de3565b611e275760405162461bcd60e51b815260040161064a9061413c565b611e2f612084565b611e7b5760405162461bcd60e51b815260206004820152601b60248201527f45706f6368206973206e6f7420726561647920746f2073746172740000000000604482015260640161064a565b6000600a5460ff166002811115611e9457611e94614048565b14611ee15760405162461bcd60e51b815260206004820181905260248201527f45706f63682070726f6365737320697320616c72656164792073746172746564604482015260640161064a565b611ee96109ad565b15611f365760405162461bcd60e51b815260206004820181905260248201527f45706f63682070726f6365737320697320616c72656164792073746172746564604482015260640161064a565b600a805460ff191660011790556006546000908152600f6020526040902043600390910155611f6361375a565b6001600160a01b03166392ecd7456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611f9d57600080fd5b505af1158015611fb1573d6000803e3d6000fd5b50505050600080600080611fc361375a565b6001600160a01b031663643470436040518163ffffffff1660e01b8152600401608060405180830381865afa158015612000573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202491906143e7565b600b849055600c839055600d829055600e8190559296509094509250905061204a613790565b6006546040517fae58a33f8b8d696bcbaca9fa29d9fdc336c140e982196c2580db3d46f3e6d4b690600090a250505050611d986001600255565b6004546006546000908152600f602052604081206002015490916120a79161441d565b421015905090565b6120b7612cb1565b6001600160a01b03811661210d5760405162461bcd60e51b815260206004820181905260248201527f43616e6e6f7420726567697374657220746865206e756c6c2061646472657373604482015260640161064a565b600180546001600160a01b0319166001600160a01b0383169081179091556040517f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b90600090a250565b600060055482101561219d5760405162461bcd60e51b815260206004820152600f60248201526e22b837b1b4103737ba1035b737bbb760891b604482015260640161064a565b60065482106121e75760405162461bcd60e51b8152602060048201526016602482015275115c1bd8da081b9bdd08199a5b9a5cda1959081e595d60521b604482015260640161064a565b506000908152600f602052604090206001015490565b60008060008061220b611de3565b6122275760405162461bcd60e51b815260040161064a9061413c565b6122326006546127d5565b935093509350935090919293565b60006001611109565b6060612253611de3565b61226f5760405162461bcd60e51b815260040161064a9061413c565b6011805480602002602001604051908101604052809291908181526020018280548015611d7c576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611d5e575050505050905090565b60005460ff16156123205760405162461bcd60e51b815260206004820152601c60248201527f636f6e747261637420616c726561647920696e697469616c697a656400000000604482015260640161064a565b6000805460ff1916600117905561233633613701565b61233f826120af565b61234881610838565b6001546040516c536f727465644f7261636c657360981b60208201526123f0916001600160a01b03169063dcf0aaed90602d01604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016123af91815260200190565b602060405180830381865afa1580156123cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103769190614189565b5050565b6123fc612240565b6124485760405162461bcd60e51b815260206004820152601c60248201527f45706f63682070726f63657373206973206e6f74207374617274656400000000604482015260640161064a565b600a805460ff19166002178155600061245f61324e565b9050600061246b6128c6565b905060006124776136cb565b6011546008549192501461249d5760405162461bcd60e51b815260040161064a90614395565b60005b6008548110156126d8576000846001600160a01b031663bb0f1fa5600884815481106124ce576124ce614173565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa15801561251e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125429190614189565b6001600160a01b038116600090815260096020526040812054919250036126c55760128054906000612573836141bf565b90915550506040516310e0415560e11b81526001600160a01b038281166004830152600091908516906321c082aa90602401602060405180830381865afa1580156125c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e691906141a6565b6002880154604051622400b960e71b81526001600160a01b038581166004830152602482019290925260448101839052919250600091908716906312005c8090606401602060405180830381865afa158015612646573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061266a91906141a6565b90508015612678578061267c565b6000195b6001600160a01b0384166000818152600960205260408082209390935560065492517f3ec722331926c18d5406855ed1fea4cd09f6bebb788160c5f43b107525d4b3329190a350505b50806126d0816141bf565b9150506124a0565b5050505050565b60006109c56109ad565b600a805460009182918291829182919060ff16600281111561270d5761270d614048565b6001820154600283015460038401546004909401549299919850965091945092509050565b60006005548210156127785760405162461bcd60e51b815260206004820152600f60248201526e22b837b1b4103737ba1035b737bbb760891b604482015260640161064a565b6006548211156127c25760405162461bcd60e51b8152602060048201526015602482015274115c1bd8da081b9bdd0818dc99585d1959081e595d605a1b604482015260640161064a565b506000908152600f602052604090205490565b6000806000806127e3611de3565b6127ff5760405162461bcd60e51b815260040161064a9061413c565b505050600091825250600f6020908152604091829020825160808101845281548082526001830154938201849052600283015494820185905260039092015460609091018190529093919291565b612855612cb1565b6001600160a01b0381166128ba5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161064a565b6128c381613701565b50565b6001546040516722b632b1ba34b7b760c11b60208201526000916001600160a01b03169063dcf0aaed906028015b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161292891815260200190565b602060405180830381865afa158015612945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c59190614189565b612974600143614332565b600680546000908152600f6020526040812060010192909255805491612999836141bf565b9091555050600680546000908152600f6020526040808220439055915481528181204260029091015581516330d35a8360e11b8152915190916001600160a01b038416916361a6b5069160048082019286929091908290030181865afa158015612a07573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612a2f9190810190614430565b8051909150612a45906008906020840190613cdf565b50612a4f81612fdc565b6000612a59613b95565b60015460405169476f7665726e616e636560b01b60208201529192506001600160a01b0380841692630357371d92919091169063dcf0aaed90602a01604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401612ac991815260200190565b602060405180830381865afa158015612ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0a9190614189565b60038701546040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015612b5557600080fd5b505af1158015612b69573d6000803e3d6000fd5b50505050806001600160a01b0316630357371d612b8461375a565b6001600160a01b03166322dae21f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be59190614189565b86600401546040518363ffffffff1660e01b8152600401612c1b9291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015612c3557600080fd5b505af1158015612c49573d6000803e3d6000fd5b5050855460ff1916865550506000600180860182905560028601829055600386018290556004860191909155600654612c829190614332565b6040517fc8e58d8e6979dd5e68bad79d4a4368a1091f6feb2323e612539b1b84e0663a8f90600090a250505050565b6000546001600160a01b03610100909104163314611d985760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161064a565b6000806000806000612d21611de3565b612d3d5760405162461bcd60e51b815260040161064a9061413c565b43861115612d995760405162461bcd60e51b8152602060048201526024808201527f496e76616c696420626c6f636b4e756d6265722e2056616c756520746f6f206860448201526334b3b41760e11b606482015260840161064a565b6000612da66005546127d5565b505050905080871015612e075760405162461bcd60e51b815260206004820152602360248201527f496e76616c696420626c6f636b4e756d6265722e2056616c756520746f6f206c60448201526237bb9760e91b606482015260840161064a565b6006546000908152600f6020526040902054808810612e4c57600080600080612e316006546127d5565b6006549e50929c50909a5098509650612fa095505050505050565b600554600654600090612e6190600190614332565b90505b808211612f3c5760006002612e79838561441d565b612e83919061446d565b6000818152600f60205260409020805460019091015491925090818d10801590612ead5750808d11155b15612f0c5750506000818152600f602090815260409182902082516080810184528154808252600183015493820184905260028301549482018590526003909201546060909101819052939c509a50985096509450612fa09350505050565b818d1015612f2657612f1f600184614332565b9350612f34565b612f3183600161441d565b94505b505050612e64565b60405162461bcd60e51b815260206004820152603360248201527f4e6f206d61746368696e672065706f636820666f756e6420666f72207468652060448201527233b4bb32b710313637b1b590373ab6b132b91760691b606482015260840161064a565b91939590929450565b6001546040516821b2b637aa37b5b2b760b91b60208201526000916001600160a01b03169063dcf0aaed906029016128f4565b6008546130375760405162461bcd60e51b815260206004820152602360248201527f456c6563746564206c697374206c656e6774682063616e6e6f74206265207a6560448201526239379760e91b606482015260840161064a565b600061304161360d565b9050815167ffffffffffffffff81111561305d5761305d613df6565b604051908082528060200260200182016040528015613086578160200160208202803683370190505b50805161309b91601191602090910190613cdf565b5060005b825181101561318b57816001600160a01b0316634ce38b5f8483815181106130c9576130c9614173565b60200260200101516040518263ffffffff1660e01b81526004016130fc91906001600160a01b0391909116815260200190565b602060405180830381865afa158015613119573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061313d9190614189565b6011828154811061315057613150614173565b600091825260209091200180546001600160a01b0319166001600160a01b039290921691909117905580613183816141bf565b91505061309f565b505050565b6040805160208101909152600081527601357c299a88ea76a58924d52ce4f26a85af186c2b9e748211156132255760405162461bcd60e51b815260206004820152603660248201527f63616e277420637265617465206669786964697479206e756d626572206c6172604482015275676572207468616e206d61784e65774669786564282960501b606482015260840161064a565b604051806020016040528069d3c21bcecceda100000084613246919061448f565b905292915050565b6001546040516956616c696461746f727360b01b60208201526000916001600160a01b03169063dcf0aaed90602a016128f4565b6040805160208101909152600081528251158061329e57508151155b156132b857506040805160208101909152600081526135ed565b815169d3c21bcecceda0ffffff19016132d25750816135ed565b825169d3c21bcecceda0ffffff19016132ec5750806135ed565b600069d3c21bcecceda100000061330285613bd5565b5161330d919061446d565b9050600061331a85613c14565b519050600069d3c21bcecceda100000061333386613bd5565b5161333e919061446d565b9050600061334b86613c14565b519050600061335a838661448f565b905084156133b3578261336d868361446d565b146133b35760405162461bcd60e51b81526020600482015260166024820152751bdd995c999b1bddc81e0c5e4c4819195d1958dd195960521b604482015260640161064a565b60006133c969d3c21bcecceda10000008361448f565b905081156134335769d3c21bcecceda10000006133e6838361446d565b146134335760405162461bcd60e51b815260206004820152601f60248201527f6f766572666c6f772078317931202a2066697865643120646574656374656400604482015260640161064a565b9050806000613442858761448f565b9050851561349b5784613455878361446d565b1461349b5760405162461bcd60e51b81526020600482015260166024820152751bdd995c999b1bddc81e0c9e4c4819195d1958dd195960521b604482015260640161064a565b60006134a7858961448f565b9050871561350057846134ba898361446d565b146135005760405162461bcd60e51b81526020600482015260166024820152751bdd995c999b1bddc81e0c5e4c8819195d1958dd195960521b604482015260640161064a565b61350f64e8d4a510008861446d565b965061352064e8d4a510008661446d565b9450600061352e868961448f565b905087156135875785613541898361446d565b146135875760405162461bcd60e51b81526020600482015260166024820152751bdd995c999b1bddc81e0c9e4c8819195d1958dd195960521b604482015260640161064a565b60408051602080820183528782528251908101909252848252906135ac908290613c5f565b90506135c681604051806020016040528086815250613c5f565b90506135e081604051806020016040528085815250613c5f565b9a50505050505050505050505b92915050565b80516000906135ed9069d3c21bcecceda10000009061446d565b600154604051674163636f756e747360c01b60208201526000916001600160a01b03169063dcf0aaed906028016128f4565b6001546040516a29ba30b13632aa37b5b2b760a91b60208201526000916001600160a01b03169063dcf0aaed90602b016128f4565b60028054036136c55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161064a565b60028055565b6001546040516b29b1b7b932a6b0b730b3b2b960a11b60208201526000916001600160a01b03169063dcf0aaed90602c016128f4565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b6001546040516b45706f63685265776172647360a01b60208201526000916001600160a01b03169063dcf0aaed90602c016128f4565b60008061379b6136cb565b905060006137a761324e565b9050600a60005b600854811015613970576000846001600160a01b031663e5079ddc600884815481106137dc576137dc614173565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa15801561382c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061385091906141a6565b90506000846001600160a01b031663087c344e6008858154811061387657613876614173565b600091825260209091200154600187015460405160e084901b6001600160e01b03191681526001600160a01b039092166004830152602482018690526044820152606401602060405180830381865afa1580156138d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138fb91906141a6565b905080601060006008868154811061391557613915614173565b60009182526020808320909101546001600160a01b031683528201929092526040018120805490919061394990849061441d565b909155506139599050818861441d565b965050508080613968906141bf565b9150506137ae565b508360000361397f5750505050565b604051633a90822b60e21b8152600481018590526001600160a01b0383169063ea4208ac90602401600060405180830381600087803b1580156139c157600080fd5b505af11580156139d5573d6000803e3d6000fd5b5050600754600092508291506001600160a01b031663efb7601d6139f761363f565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526024016040805180830381865afa158015613a3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a5e91906144a6565b9092509050600081613a70888561448f565b613a7a919061446d565b9050613a84613b95565b600154604051665265736572766560c81b60208201526001600160a01b0392831692630357371d92169063dcf0aaed90602701604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401613aeb91815260200190565b602060405180830381865afa158015613b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b2c9190614189565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b158015613b7457600080fd5b505af1158015613b88573d6000803e3d6000fd5b5050505050505050505050565b6001546040517543656c6f556e72656c6561736564547265617375727960501b60208201526000916001600160a01b03169063dcf0aaed906036016128f4565b604080516020810190915260008152604051806020016040528069d3c21bcecceda1000000808560000151613c0a919061446d565b613246919061448f565b604080516020810190915260008152604051806020016040528069d3c21bcecceda1000000808560000151613c49919061446d565b613c53919061448f565b84516132469190614332565b60408051602081019091526000815281518351600091613c7e9161441d565b8451909150811015613cca5760405162461bcd60e51b8152602060048201526015602482015274185919081bdd995c999b1bddc819195d1958dd1959605a1b604482015260640161064a565b60408051602081019091529081529392505050565b828054828255906000526020600020908101928215613d34579160200282015b82811115613d3457825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613cff565b50613d40929150613d44565b5090565b5b80821115613d405760008155600101613d45565b6001600160a01b03811681146128c357600080fd5b600060208284031215613d8057600080fd5b8135613d8b81613d59565b9392505050565b600080600060608486031215613da757600080fd5b8335613db281613d59565b92506020840135613dc281613d59565b91506040840135613dd281613d59565b809150509250925092565b600060208284031215613def57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613e3557613e35613df6565b604052919050565b600067ffffffffffffffff821115613e5757613e57613df6565b5060051b60200190565b600080600060608486031215613e7657600080fd5b833592506020808501359250604085013567ffffffffffffffff811115613e9c57600080fd5b8501601f81018713613ead57600080fd5b8035613ec0613ebb82613e3d565b613e0c565b81815260059190911b82018301908381019089831115613edf57600080fd5b928401925b82841015613f06578335613ef781613d59565b82529284019290840190613ee4565b80955050505050509250925092565b60008083601f840112613f2757600080fd5b50813567ffffffffffffffff811115613f3f57600080fd5b6020830191508360208260051b8501011115613f5a57600080fd5b9250929050565b60008060008060008060608789031215613f7a57600080fd5b863567ffffffffffffffff80821115613f9257600080fd5b613f9e8a838b01613f15565b90985096506020890135915080821115613fb757600080fd5b613fc38a838b01613f15565b90965094506040890135915080821115613fdc57600080fd5b50613fe989828a01613f15565b979a9699509497509295939492505050565b6020808252825182820181905260009190848201906040850190845b8181101561403c5783516001600160a01b031683529284019291840191600101614017565b50909695505050505050565b634e487b7160e01b600052602160045260246000fd5b60a081016003871061408057634e487b7160e01b600052602160045260246000fd5b95815260208101949094526040840192909252606083015260809091015290565b600080604083850312156140b457600080fd5b82356140bf81613d59565b946020939093013593505050565b60208082526022908201527f67726f7570206e6f742066726f6d2063757272656e7420656c65637465642073604082015261195d60f21b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6000816141345761413461410f565b506000190190565b6020808252601c908201527f45706f63682073797374656d206e6f7420696e697469616c697a656400000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561419b57600080fd5b8151613d8b81613d59565b6000602082840312156141b857600080fd5b5051919050565b6000600182016141d1576141d161410f565b5060010190565b600082601f8301126141e957600080fd5b815160206141f9613ebb83613e3d565b82815260059290921b8401810191818101908684111561421857600080fd5b8286015b8481101561423c57805161422f81613d59565b835291830191830161421c565b509695505050505050565b600080600080600080600060e0888a03121561426257600080fd5b875167ffffffffffffffff8082111561427a57600080fd5b6142868b838c016141d8565b985060209150818a0151975060408a0151965060608a0151955060808a0151818111156142b257600080fd5b8a019050601f81018b136142c557600080fd5b80516142d3613ebb82613e3d565b81815260059190911b8201830190838101908d8311156142f257600080fd5b928401925b82841015614310578351825292840192908401906142f7565b809750505050505060a0880151915060c0880151905092959891949750929550565b818103818111156135ed576135ed61410f565b6000806040838503121561435857600080fd5b825161436381613d59565b6020939093015192949293505050565b60006020828403121561438557600080fd5b81518015158114613d8b57600080fd5b60208082526032908201527f456c6563746564206163636f756e747320616e64207369676e657273206f66206040820152713234b33332b932b73a103632b733ba34399760711b606082015260800190565b600080600080608085870312156143fd57600080fd5b505082516020840151604085015160609095015191969095509092509050565b808201808211156135ed576135ed61410f565b60006020828403121561444257600080fd5b815167ffffffffffffffff81111561445957600080fd5b614465848285016141d8565b949350505050565b60008261448a57634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176135ed576135ed61410f565b600080604083850312156144b957600080fd5b50508051602090910151909290915056fea264697066735822122069b5db76bab2d7411c2a04303e2c7ca0c9f04797893d2f480f61d2b8e9c5e9bb64736f6c634300081300330000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061028a5760003560e01c80638657f6151161015c578063b5a842cd116100ce578063d75f0da711610087578063d75f0da71461056e578063ebf52c5114610576578063ef0551d1146105a6578063f1542de5146105b9578063f1fcbab1146105cc578063f2fde38b146105d557600080fd5b8063b5a842cd14610528578063b97dd9e21461053b578063ba18ee4d14610543578063bd5a0a351461054b578063cd6dc68714610553578063d02cfcf31461056657600080fd5b806398f6c7601161012057806398f6c760146104ca5780639b217558146104ea5780639f3bf7a0146104f2578063a0fa0d56146104fa578063a89ae4ba14610502578063a91ee0dc1461051557600080fd5b80638657f61514610457578063891c48fb1461046a5780638c25656e146104735780638da5cb5b1461048657806398b509051461049c57600080fd5b806351ccd8f01161020057806364c2c255116101b957806364c2c255146103f4578063653c356f14610401578063667f331b146104145780636857f6a114610427578063715018a61461043c5780637b1039991461044457600080fd5b806351ccd8f01461038457806352ba62621461039757806354255be0146103aa57806354454b48146103d15780635915e077146103d9578063639a84d3146103ec57600080fd5b80633a65c499116102525780633a65c499146103325780633b1eb4bf146103455780634406d661146103585780634408d2ba146103605780634c69c00f146103685780634ff0876a1461037b57600080fd5b8063158ef93e1461028f578063186b978d146102b1578063210b315b146102df5780632ba47274146102f457806330024dfe1461031f575b600080fd5b60005461029c9060ff1681565b60405190151581526020015b60405180910390f35b6102d16102bf366004613d6e565b60096020526000908152604090205481565b6040519081526020016102a8565b6102f26102ed366004613d92565b6105e8565b005b610307610302366004613ddd565b6107e4565b6040516001600160a01b0390911681526020016102a8565b6102f261032d366004613ddd565b610838565b610307610340366004613ddd565b610946565b6102d1610353366004613ddd565b610970565b61029c6109ad565b6102d16109ca565b6102f2610376366004613d6e565b6109f7565b6102d160045481565b6102f2610392366004613e61565b610b8a565b6102f26103a5366004613f61565b611066565b6001806000805b6040805194855260208501939093529183015260608201526080016102a8565b61029c611104565b6102f26103e7366004613d6e565b611126565b6102d1611663565b60035461029c9060ff1681565b6103b161040f366004613ddd565b611690565b6102f2610422366004613f61565b6116dd565b61042f611d00565b6040516102a89190613ffb565b6102f2611d86565b600154610307906001600160a01b031681565b610307610465366004613ddd565b611d9a565b6102d160055481565b610307610481366004613ddd565b611dd3565b60005461010090046001600160a01b0316610307565b600a54600b54600c54600d54600e546104b99460ff169392919085565b6040516102a895949392919061405e565b6102d16104d8366004613d6e565b60106020526000908152604090205481565b61029c611de3565b6102f2611dfb565b61029c612084565b600754610307906001600160a01b031681565b6102f2610523366004613d6e565b6120af565b6102d1610536366004613ddd565b612157565b6103b16121fd565b61029c612240565b61042f612249565b6102f26105613660046140a1565b6122cd565b6102f26123f4565b61029c6126df565b61057e6126e9565b604080519586526020860194909452928401919091526060830152608082015260a0016102a8565b6102d16105b4366004613ddd565b612732565b6103b16105c7366004613ddd565b6127d5565b6102d160125481565b6102f26105e3366004613d6e565b61284d565b600a6105f2611104565b6106535760405162461bcd60e51b815260206004820152602760248201527f496e646976756475616c2065706f63682070726f63657373206973206e6f74206044820152661cdd185c9d195960ca1b60648201526084015b60405180910390fd5b6000601254116106a55760405162461bcd60e51b815260206004820152601960248201527f6e6f206d6f72652067726f75707320746f2070726f6365737300000000000000604482015260640161064a565b6001600160a01b038416600090815260096020526040902054806106db5760405162461bcd60e51b815260040161064a906140cd565b60006106e56128c6565b90506000198214610763576040516312541a6b60e01b81526001600160a01b03878116600483015260248201849052868116604483015285811660648301528216906312541a6b90608401600060405180830381600087803b15801561074a57600080fd5b505af115801561075e573d6000803e3d6000fd5b505050505b6001600160a01b0386166000908152600960205260408120819055601280549161078c83614125565b90915550506006546040516001600160a01b038816907f15ff42ed3ffc7d45600460c399f3a885b3c25e0c4f613266e5fbd5dc80ea14c790600090a36012546000036107dc576107dc8382612969565b505050505050565b60006107ee611de3565b61080a5760405162461bcd60e51b815260040161064a9061413c565b6011828154811061081d5761081d614173565b6000918252602090912001546001600160a01b031692915050565b610840612cb1565b600081116108a65760405162461bcd60e51b815260206004820152602d60248201527f4e65772065706f6368206475726174696f6e206d75737420626520677265617460448201526c32b9103a3430b7103d32b9379760991b606482015260840161064a565b6108ae612240565b156109135760405162461bcd60e51b815260206004820152602f60248201527f43616e6e6f74206368616e67652065706f6368206475726174696f6e2064757260448201526e34b73390383937b1b2b9b9b4b7339760891b606482015260840161064a565b600481905560405181907fe018a3a09e27f3987d8cbe7e32e55899996a50099fb79f333c0030831842eeb090600090a250565b6011818154811061095657600080fd5b6000918252602090912001546001600160a01b0316905081565b600061097a611de3565b6109965760405162461bcd60e51b815260040161064a9061413c565b60006109a183612d11565b50929695505050505050565b60006109b7612240565b806109c557506109c5611104565b905090565b60006109d4611de3565b6109f05760405162461bcd60e51b815260040161064a9061413c565b5060065490565b6109ff612cb1565b6001600160a01b038116610a645760405162461bcd60e51b815260206004820152602660248201527f43616e6e6f74207365742061646472657373207a65726f20617320746865204f6044820152653930b1b6329760d11b606482015260840161064a565b6007546001600160a01b0390811690821603610acd5760405162461bcd60e51b815260206004820152602260248201527f4f7261636c6520616464726573732063616e6e6f74206265207468652073616d604482015261329760f11b606482015260840161064a565b610ad5612240565b15610b405760405162461bcd60e51b815260206004820152603560248201527f43616e6e6f74206368616e6765206f7261636c6520616464726573732064757260448201527434b7339032b837b1b410383937b1b2b9b9b4b7339760591b606482015260840161064a565b600780546001600160a01b0319166001600160a01b0383169081179091556040517fdd82bdfc28fcc826c53263dc2a2b6083e27e92699ebfee617227e08e21c202f090600090a250565b6001546040517222b837b1b426b0b730b3b2b922b730b13632b960691b60208201526001600160a01b039091169063dcf0aaed90603301604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610bf591815260200190565b602060405180830381865afa158015610c12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c369190614189565b6001600160a01b0316336001600160a01b031614610c965760405162461bcd60e51b815260206004820152601960248201527f6d73672e73656e646572206973206e6f7420456e61626c657200000000000000604482015260640161064a565b6000610ca0612fa9565b6001546040517543656c6f556e72656c6561736564547265617375727960501b60208201526001600160a01b03928316926370a0823192169063dcf0aaed90603601604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610d1691815260200190565b602060405180830381865afa158015610d33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d579190614189565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610d9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbf91906141a6565b11610e1b5760405162461bcd60e51b815260206004820152602660248201527f43656c6f556e72656c65617365645472656173757279206e6f742079657420666044820152653ab73232b21760d11b606482015260840161064a565b610e23611de3565b15610e705760405162461bcd60e51b815260206004820181905260248201527f45706f63682073797374656d20616c726561647920696e697469616c697a6564604482015260640161064a565b60008311610ed25760405162461bcd60e51b815260206004820152602960248201527f46697273742065706f6368206e756d626572206d75737420626520677265617460448201526806572207468616e20360bc1b606482015260840161064a565b60008211610f335760405162461bcd60e51b815260206004820152602860248201527f46697273742065706f636820626c6f636b206d75737420626520677265617465604482015267072207468616e20360c41b606482015260840161064a565b43821115610fa95760405162461bcd60e51b815260206004820152603a60248201527f46697273742065706f636820626c6f636b206d757374206265206c657373206f60448201527f7220657175616c207468616e2063757272656e7420626c6f636b000000000000606482015260840161064a565b60008151116110125760405162461bcd60e51b815260206004820152602f60248201527f466972737420656c65637465642076616c696461746f7273206d75737420626560448201526e02067726561746572207468616e203608c1b606482015260840161064a565b6003805460ff19166001179055600583905560068390556000838152600f602090815260409091208381554260028201558251909161105691600891850190613cdf565b5061106082612fdc565b50505050565b60005b858110156110fb576110e987878381811061108657611086614173565b905060200201602081019061109b9190613d6e565b8686848181106110ad576110ad614173565b90506020020160208101906110c29190613d6e565b8585858181106110d4576110d4614173565b90506020020160208101906102ed9190613d6e565b806110f3816141bf565b915050611069565b50505050505050565b600060025b600a5460ff16600281111561112057611120614048565b14905090565b61112e611de3565b61114a5760405162461bcd60e51b815260040161064a9061413c565b6001600160a01b03811660009081526010602052604081205461116c90613190565b6001600160a01b038316600090815260106020526040812081905590915061119261324e565b60405163bb0f1fa560e01b81526001600160a01b03858116600483015291925060009183169063bb0f1fa590602401602060405180830381865afa1580156111de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112029190614189565b604051639b9d516160e01b81526001600160a01b038083166004830152919250600091841690639b9d516190602401600060405180830381865afa15801561124e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112769190810190614247565b505050505091505060006112b46112af6112a88460408051602080820183526000909152815190810190915290815290565b8790613282565b6135f3565b905060006112d4826112c5886135f3565b6112cf9190614332565b613190565b90506000806112e161360d565b604051639f024f4b60e01b81526001600160a01b038b811660048301529190911690639f024f4b906024016040805180830381865afa158015611328573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134c9190614345565b9150915060006113816112af61137a8460408051602080820183526000909152815190810190915290815290565b8690613282565b905060008161138f866135f3565b6113999190614332565b905060006113a561363f565b9050811561146c5760405163a9059cbb60e01b81526001600160a01b038d811660048301526024820184905282169063a9059cbb906044016020604051808303816000875af11580156113fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114209190614373565b61146c5760405162461bcd60e51b815260206004820152601c60248201527f7472616e73666572206661696c656420746f2076616c696461746f7200000000604482015260640161064a565b861561153c5760405163a9059cbb60e01b81526001600160a01b038a811660048301526024820189905282169063a9059cbb906044016020604051808303816000875af11580156114c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e59190614373565b61153c5760405162461bcd60e51b815260206004820152602260248201527f7472616e73666572206661696c656420746f2076616c696461746f722067726f604482015261075760f41b606482015260840161064a565b82156116015760405163a9059cbb60e01b81526001600160a01b0386811660048301526024820185905282169063a9059cbb906044016020604051808303816000875af1158015611591573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b59190614373565b6116015760405162461bcd60e51b815260206004820152601c60248201527f7472616e73666572206661696c656420746f2064656c65676174656500000000604482015260640161064a565b60408051838152602081018990529081018490526001600160a01b03808716918b8216918f16907fee2788e7abedfc61d9608e143b172de1a608a4298b06ed8c84838aa0ad6bd1369060600160405180910390a4505050505050505050505050565b600061166d611de3565b6116895760405162461bcd60e51b815260040161064a9061413c565b5060085490565b60008060008061169e611de3565b6116ba5760405162461bcd60e51b815260040161064a9061413c565b6000806000806116c989612d11565b929d919c509a509098509650505050505050565b6116e5613674565b6116ed612240565b6117395760405162461bcd60e51b815260206004820152601c60248201527f45706f63682070726f63657373206973206e6f74207374617274656400000000604482015260640161064a565b601254156117af5760405162461bcd60e51b815260206004820152603e60248201527f43616e27742066696e6973682065706f6368207768696c6520696e646976696460448201527f75616c2067726f75707320617265206265696e672070726f6365737365640000606482015260840161064a565b600a6000806117bc61324e565b905060006117c86128c6565b905060006117d46136cb565b601154600854919250146117fa5760405162461bcd60e51b815260040161064a90614395565b60005b600854811015611a5a576000846001600160a01b031663bb0f1fa56008848154811061182b5761182b614173565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa15801561187b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189f9190614189565b6001600160a01b038116600090815260096020526040812054919250036119ee57856118ca816141bf565b6040516310e0415560e11b81526001600160a01b03848116600483015291985060009250908516906321c082aa90602401602060405180830381865afa158015611918573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193c91906141a6565b6002890154604051622400b960e71b81526001600160a01b038581166004830152602482019290925260448101839052919250600091908716906312005c8090606401602060405180830381865afa15801561199c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c091906141a6565b905080156119ce57806119d2565b6000195b6001600160a01b03841660009081526009602052604090205550505b60088281548110611a0157611a01614173565b600091825260209091200180546001600160a01b03191690556011805483908110611a2e57611a2e614173565b600091825260209091200180546001600160a01b03191690555080611a52816141bf565b9150506117fd565b50838a14611aaa5760405162461bcd60e51b815260206004820152601f60248201527f6e756d626572206f662067726f75707320646f6573206e6f74206d6174636800604482015260640161064a565b60005b8a811015611ce6576000600960008e8e85818110611acd57611acd614173565b9050602002016020810190611ae29190613d6e565b6001600160a01b03166001600160a01b0316815260200190815260200160002054905060008111611b255760405162461bcd60e51b815260040161064a906140cd565b6000198114611c2557836001600160a01b03166312541a6b8e8e85818110611b4f57611b4f614173565b9050602002016020810190611b649190613d6e565b838e8e87818110611b7757611b77614173565b9050602002016020810190611b8c9190613d6e565b8d8d88818110611b9e57611b9e614173565b9050602002016020810190611bb39190613d6e565b60405160e086901b6001600160e01b03191681526001600160a01b039485166004820152602481019390935290831660448301529091166064820152608401600060405180830381600087803b158015611c0c57600080fd5b505af1158015611c20573d6000803e3d6000fd5b505050505b600960008e8e85818110611c3b57611c3b614173565b9050602002016020810190611c509190613d6e565b6001600160a01b03166001600160a01b03168152602001908152602001600020600090556006548d8d84818110611c8957611c89614173565b9050602002016020810190611c9e9190613d6e565b6001600160a01b03167f15ff42ed3ffc7d45600460c399f3a885b3c25e0c4f613266e5fbd5dc80ea14c760405160405180910390a35080611cde816141bf565b915050611aad565b50611cf18583612969565b50505050506107dc6001600255565b6060611d0a611de3565b611d265760405162461bcd60e51b815260040161064a9061413c565b6008805480602002602001604051908101604052809291908181526020018280548015611d7c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611d5e575b5050505050905090565b611d8e612cb1565b611d986000613701565b565b6000611da4611de3565b611dc05760405162461bcd60e51b815260040161064a9061413c565b6008828154811061081d5761081d614173565b6008818154811061095657600080fd5b6000805460ff1680156109c557505060035460ff1690565b611e03613674565b611e0b611de3565b611e275760405162461bcd60e51b815260040161064a9061413c565b611e2f612084565b611e7b5760405162461bcd60e51b815260206004820152601b60248201527f45706f6368206973206e6f7420726561647920746f2073746172740000000000604482015260640161064a565b6000600a5460ff166002811115611e9457611e94614048565b14611ee15760405162461bcd60e51b815260206004820181905260248201527f45706f63682070726f6365737320697320616c72656164792073746172746564604482015260640161064a565b611ee96109ad565b15611f365760405162461bcd60e51b815260206004820181905260248201527f45706f63682070726f6365737320697320616c72656164792073746172746564604482015260640161064a565b600a805460ff191660011790556006546000908152600f6020526040902043600390910155611f6361375a565b6001600160a01b03166392ecd7456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611f9d57600080fd5b505af1158015611fb1573d6000803e3d6000fd5b50505050600080600080611fc361375a565b6001600160a01b031663643470436040518163ffffffff1660e01b8152600401608060405180830381865afa158015612000573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202491906143e7565b600b849055600c839055600d829055600e8190559296509094509250905061204a613790565b6006546040517fae58a33f8b8d696bcbaca9fa29d9fdc336c140e982196c2580db3d46f3e6d4b690600090a250505050611d986001600255565b6004546006546000908152600f602052604081206002015490916120a79161441d565b421015905090565b6120b7612cb1565b6001600160a01b03811661210d5760405162461bcd60e51b815260206004820181905260248201527f43616e6e6f7420726567697374657220746865206e756c6c2061646472657373604482015260640161064a565b600180546001600160a01b0319166001600160a01b0383169081179091556040517f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b90600090a250565b600060055482101561219d5760405162461bcd60e51b815260206004820152600f60248201526e22b837b1b4103737ba1035b737bbb760891b604482015260640161064a565b60065482106121e75760405162461bcd60e51b8152602060048201526016602482015275115c1bd8da081b9bdd08199a5b9a5cda1959081e595d60521b604482015260640161064a565b506000908152600f602052604090206001015490565b60008060008061220b611de3565b6122275760405162461bcd60e51b815260040161064a9061413c565b6122326006546127d5565b935093509350935090919293565b60006001611109565b6060612253611de3565b61226f5760405162461bcd60e51b815260040161064a9061413c565b6011805480602002602001604051908101604052809291908181526020018280548015611d7c576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611d5e575050505050905090565b60005460ff16156123205760405162461bcd60e51b815260206004820152601c60248201527f636f6e747261637420616c726561647920696e697469616c697a656400000000604482015260640161064a565b6000805460ff1916600117905561233633613701565b61233f826120af565b61234881610838565b6001546040516c536f727465644f7261636c657360981b60208201526123f0916001600160a01b03169063dcf0aaed90602d01604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016123af91815260200190565b602060405180830381865afa1580156123cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103769190614189565b5050565b6123fc612240565b6124485760405162461bcd60e51b815260206004820152601c60248201527f45706f63682070726f63657373206973206e6f74207374617274656400000000604482015260640161064a565b600a805460ff19166002178155600061245f61324e565b9050600061246b6128c6565b905060006124776136cb565b6011546008549192501461249d5760405162461bcd60e51b815260040161064a90614395565b60005b6008548110156126d8576000846001600160a01b031663bb0f1fa5600884815481106124ce576124ce614173565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa15801561251e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125429190614189565b6001600160a01b038116600090815260096020526040812054919250036126c55760128054906000612573836141bf565b90915550506040516310e0415560e11b81526001600160a01b038281166004830152600091908516906321c082aa90602401602060405180830381865afa1580156125c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e691906141a6565b6002880154604051622400b960e71b81526001600160a01b038581166004830152602482019290925260448101839052919250600091908716906312005c8090606401602060405180830381865afa158015612646573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061266a91906141a6565b90508015612678578061267c565b6000195b6001600160a01b0384166000818152600960205260408082209390935560065492517f3ec722331926c18d5406855ed1fea4cd09f6bebb788160c5f43b107525d4b3329190a350505b50806126d0816141bf565b9150506124a0565b5050505050565b60006109c56109ad565b600a805460009182918291829182919060ff16600281111561270d5761270d614048565b6001820154600283015460038401546004909401549299919850965091945092509050565b60006005548210156127785760405162461bcd60e51b815260206004820152600f60248201526e22b837b1b4103737ba1035b737bbb760891b604482015260640161064a565b6006548211156127c25760405162461bcd60e51b8152602060048201526015602482015274115c1bd8da081b9bdd0818dc99585d1959081e595d605a1b604482015260640161064a565b506000908152600f602052604090205490565b6000806000806127e3611de3565b6127ff5760405162461bcd60e51b815260040161064a9061413c565b505050600091825250600f6020908152604091829020825160808101845281548082526001830154938201849052600283015494820185905260039092015460609091018190529093919291565b612855612cb1565b6001600160a01b0381166128ba5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161064a565b6128c381613701565b50565b6001546040516722b632b1ba34b7b760c11b60208201526000916001600160a01b03169063dcf0aaed906028015b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161292891815260200190565b602060405180830381865afa158015612945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c59190614189565b612974600143614332565b600680546000908152600f6020526040812060010192909255805491612999836141bf565b9091555050600680546000908152600f6020526040808220439055915481528181204260029091015581516330d35a8360e11b8152915190916001600160a01b038416916361a6b5069160048082019286929091908290030181865afa158015612a07573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612a2f9190810190614430565b8051909150612a45906008906020840190613cdf565b50612a4f81612fdc565b6000612a59613b95565b60015460405169476f7665726e616e636560b01b60208201529192506001600160a01b0380841692630357371d92919091169063dcf0aaed90602a01604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401612ac991815260200190565b602060405180830381865afa158015612ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0a9190614189565b60038701546040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015612b5557600080fd5b505af1158015612b69573d6000803e3d6000fd5b50505050806001600160a01b0316630357371d612b8461375a565b6001600160a01b03166322dae21f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be59190614189565b86600401546040518363ffffffff1660e01b8152600401612c1b9291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015612c3557600080fd5b505af1158015612c49573d6000803e3d6000fd5b5050855460ff1916865550506000600180860182905560028601829055600386018290556004860191909155600654612c829190614332565b6040517fc8e58d8e6979dd5e68bad79d4a4368a1091f6feb2323e612539b1b84e0663a8f90600090a250505050565b6000546001600160a01b03610100909104163314611d985760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161064a565b6000806000806000612d21611de3565b612d3d5760405162461bcd60e51b815260040161064a9061413c565b43861115612d995760405162461bcd60e51b8152602060048201526024808201527f496e76616c696420626c6f636b4e756d6265722e2056616c756520746f6f206860448201526334b3b41760e11b606482015260840161064a565b6000612da66005546127d5565b505050905080871015612e075760405162461bcd60e51b815260206004820152602360248201527f496e76616c696420626c6f636b4e756d6265722e2056616c756520746f6f206c60448201526237bb9760e91b606482015260840161064a565b6006546000908152600f6020526040902054808810612e4c57600080600080612e316006546127d5565b6006549e50929c50909a5098509650612fa095505050505050565b600554600654600090612e6190600190614332565b90505b808211612f3c5760006002612e79838561441d565b612e83919061446d565b6000818152600f60205260409020805460019091015491925090818d10801590612ead5750808d11155b15612f0c5750506000818152600f602090815260409182902082516080810184528154808252600183015493820184905260028301549482018590526003909201546060909101819052939c509a50985096509450612fa09350505050565b818d1015612f2657612f1f600184614332565b9350612f34565b612f3183600161441d565b94505b505050612e64565b60405162461bcd60e51b815260206004820152603360248201527f4e6f206d61746368696e672065706f636820666f756e6420666f72207468652060448201527233b4bb32b710313637b1b590373ab6b132b91760691b606482015260840161064a565b91939590929450565b6001546040516821b2b637aa37b5b2b760b91b60208201526000916001600160a01b03169063dcf0aaed906029016128f4565b6008546130375760405162461bcd60e51b815260206004820152602360248201527f456c6563746564206c697374206c656e6774682063616e6e6f74206265207a6560448201526239379760e91b606482015260840161064a565b600061304161360d565b9050815167ffffffffffffffff81111561305d5761305d613df6565b604051908082528060200260200182016040528015613086578160200160208202803683370190505b50805161309b91601191602090910190613cdf565b5060005b825181101561318b57816001600160a01b0316634ce38b5f8483815181106130c9576130c9614173565b60200260200101516040518263ffffffff1660e01b81526004016130fc91906001600160a01b0391909116815260200190565b602060405180830381865afa158015613119573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061313d9190614189565b6011828154811061315057613150614173565b600091825260209091200180546001600160a01b0319166001600160a01b039290921691909117905580613183816141bf565b91505061309f565b505050565b6040805160208101909152600081527601357c299a88ea76a58924d52ce4f26a85af186c2b9e748211156132255760405162461bcd60e51b815260206004820152603660248201527f63616e277420637265617465206669786964697479206e756d626572206c6172604482015275676572207468616e206d61784e65774669786564282960501b606482015260840161064a565b604051806020016040528069d3c21bcecceda100000084613246919061448f565b905292915050565b6001546040516956616c696461746f727360b01b60208201526000916001600160a01b03169063dcf0aaed90602a016128f4565b6040805160208101909152600081528251158061329e57508151155b156132b857506040805160208101909152600081526135ed565b815169d3c21bcecceda0ffffff19016132d25750816135ed565b825169d3c21bcecceda0ffffff19016132ec5750806135ed565b600069d3c21bcecceda100000061330285613bd5565b5161330d919061446d565b9050600061331a85613c14565b519050600069d3c21bcecceda100000061333386613bd5565b5161333e919061446d565b9050600061334b86613c14565b519050600061335a838661448f565b905084156133b3578261336d868361446d565b146133b35760405162461bcd60e51b81526020600482015260166024820152751bdd995c999b1bddc81e0c5e4c4819195d1958dd195960521b604482015260640161064a565b60006133c969d3c21bcecceda10000008361448f565b905081156134335769d3c21bcecceda10000006133e6838361446d565b146134335760405162461bcd60e51b815260206004820152601f60248201527f6f766572666c6f772078317931202a2066697865643120646574656374656400604482015260640161064a565b9050806000613442858761448f565b9050851561349b5784613455878361446d565b1461349b5760405162461bcd60e51b81526020600482015260166024820152751bdd995c999b1bddc81e0c9e4c4819195d1958dd195960521b604482015260640161064a565b60006134a7858961448f565b9050871561350057846134ba898361446d565b146135005760405162461bcd60e51b81526020600482015260166024820152751bdd995c999b1bddc81e0c5e4c8819195d1958dd195960521b604482015260640161064a565b61350f64e8d4a510008861446d565b965061352064e8d4a510008661446d565b9450600061352e868961448f565b905087156135875785613541898361446d565b146135875760405162461bcd60e51b81526020600482015260166024820152751bdd995c999b1bddc81e0c9e4c8819195d1958dd195960521b604482015260640161064a565b60408051602080820183528782528251908101909252848252906135ac908290613c5f565b90506135c681604051806020016040528086815250613c5f565b90506135e081604051806020016040528085815250613c5f565b9a50505050505050505050505b92915050565b80516000906135ed9069d3c21bcecceda10000009061446d565b600154604051674163636f756e747360c01b60208201526000916001600160a01b03169063dcf0aaed906028016128f4565b6001546040516a29ba30b13632aa37b5b2b760a91b60208201526000916001600160a01b03169063dcf0aaed90602b016128f4565b60028054036136c55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161064a565b60028055565b6001546040516b29b1b7b932a6b0b730b3b2b960a11b60208201526000916001600160a01b03169063dcf0aaed90602c016128f4565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b6001546040516b45706f63685265776172647360a01b60208201526000916001600160a01b03169063dcf0aaed90602c016128f4565b60008061379b6136cb565b905060006137a761324e565b9050600a60005b600854811015613970576000846001600160a01b031663e5079ddc600884815481106137dc576137dc614173565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa15801561382c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061385091906141a6565b90506000846001600160a01b031663087c344e6008858154811061387657613876614173565b600091825260209091200154600187015460405160e084901b6001600160e01b03191681526001600160a01b039092166004830152602482018690526044820152606401602060405180830381865afa1580156138d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138fb91906141a6565b905080601060006008868154811061391557613915614173565b60009182526020808320909101546001600160a01b031683528201929092526040018120805490919061394990849061441d565b909155506139599050818861441d565b965050508080613968906141bf565b9150506137ae565b508360000361397f5750505050565b604051633a90822b60e21b8152600481018590526001600160a01b0383169063ea4208ac90602401600060405180830381600087803b1580156139c157600080fd5b505af11580156139d5573d6000803e3d6000fd5b5050600754600092508291506001600160a01b031663efb7601d6139f761363f565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526024016040805180830381865afa158015613a3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a5e91906144a6565b9092509050600081613a70888561448f565b613a7a919061446d565b9050613a84613b95565b600154604051665265736572766560c81b60208201526001600160a01b0392831692630357371d92169063dcf0aaed90602701604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401613aeb91815260200190565b602060405180830381865afa158015613b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b2c9190614189565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b158015613b7457600080fd5b505af1158015613b88573d6000803e3d6000fd5b5050505050505050505050565b6001546040517543656c6f556e72656c6561736564547265617375727960501b60208201526000916001600160a01b03169063dcf0aaed906036016128f4565b604080516020810190915260008152604051806020016040528069d3c21bcecceda1000000808560000151613c0a919061446d565b613246919061448f565b604080516020810190915260008152604051806020016040528069d3c21bcecceda1000000808560000151613c49919061446d565b613c53919061448f565b84516132469190614332565b60408051602081019091526000815281518351600091613c7e9161441d565b8451909150811015613cca5760405162461bcd60e51b8152602060048201526015602482015274185919081bdd995c999b1bddc819195d1958dd1959605a1b604482015260640161064a565b60408051602081019091529081529392505050565b828054828255906000526020600020908101928215613d34579160200282015b82811115613d3457825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613cff565b50613d40929150613d44565b5090565b5b80821115613d405760008155600101613d45565b6001600160a01b03811681146128c357600080fd5b600060208284031215613d8057600080fd5b8135613d8b81613d59565b9392505050565b600080600060608486031215613da757600080fd5b8335613db281613d59565b92506020840135613dc281613d59565b91506040840135613dd281613d59565b809150509250925092565b600060208284031215613def57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613e3557613e35613df6565b604052919050565b600067ffffffffffffffff821115613e5757613e57613df6565b5060051b60200190565b600080600060608486031215613e7657600080fd5b833592506020808501359250604085013567ffffffffffffffff811115613e9c57600080fd5b8501601f81018713613ead57600080fd5b8035613ec0613ebb82613e3d565b613e0c565b81815260059190911b82018301908381019089831115613edf57600080fd5b928401925b82841015613f06578335613ef781613d59565b82529284019290840190613ee4565b80955050505050509250925092565b60008083601f840112613f2757600080fd5b50813567ffffffffffffffff811115613f3f57600080fd5b6020830191508360208260051b8501011115613f5a57600080fd5b9250929050565b60008060008060008060608789031215613f7a57600080fd5b863567ffffffffffffffff80821115613f9257600080fd5b613f9e8a838b01613f15565b90985096506020890135915080821115613fb757600080fd5b613fc38a838b01613f15565b90965094506040890135915080821115613fdc57600080fd5b50613fe989828a01613f15565b979a9699509497509295939492505050565b6020808252825182820181905260009190848201906040850190845b8181101561403c5783516001600160a01b031683529284019291840191600101614017565b50909695505050505050565b634e487b7160e01b600052602160045260246000fd5b60a081016003871061408057634e487b7160e01b600052602160045260246000fd5b95815260208101949094526040840192909252606083015260809091015290565b600080604083850312156140b457600080fd5b82356140bf81613d59565b946020939093013593505050565b60208082526022908201527f67726f7570206e6f742066726f6d2063757272656e7420656c65637465642073604082015261195d60f21b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6000816141345761413461410f565b506000190190565b6020808252601c908201527f45706f63682073797374656d206e6f7420696e697469616c697a656400000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561419b57600080fd5b8151613d8b81613d59565b6000602082840312156141b857600080fd5b5051919050565b6000600182016141d1576141d161410f565b5060010190565b600082601f8301126141e957600080fd5b815160206141f9613ebb83613e3d565b82815260059290921b8401810191818101908684111561421857600080fd5b8286015b8481101561423c57805161422f81613d59565b835291830191830161421c565b509695505050505050565b600080600080600080600060e0888a03121561426257600080fd5b875167ffffffffffffffff8082111561427a57600080fd5b6142868b838c016141d8565b985060209150818a0151975060408a0151965060608a0151955060808a0151818111156142b257600080fd5b8a019050601f81018b136142c557600080fd5b80516142d3613ebb82613e3d565b81815260059190911b8201830190838101908d8311156142f257600080fd5b928401925b82841015614310578351825292840192908401906142f7565b809750505050505060a0880151915060c0880151905092959891949750929550565b818103818111156135ed576135ed61410f565b6000806040838503121561435857600080fd5b825161436381613d59565b6020939093015192949293505050565b60006020828403121561438557600080fd5b81518015158114613d8b57600080fd5b60208082526032908201527f456c6563746564206163636f756e747320616e64207369676e657273206f66206040820152713234b33332b932b73a103632b733ba34399760711b606082015260800190565b600080600080608085870312156143fd57600080fd5b505082516020840151604085015160609095015191969095509092509050565b808201808211156135ed576135ed61410f565b60006020828403121561444257600080fd5b815167ffffffffffffffff81111561445957600080fd5b614465848285016141d8565b949350505050565b60008261448a57634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176135ed576135ed61410f565b600080604083850312156144b957600080fd5b50508051602090910151909290915056fea264697066735822122069b5db76bab2d7411c2a04303e2c7ca0c9f04797893d2f480f61d2b8e9c5e9bb64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : test (bool): True
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000001
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.