Overview
S Balance
0 S
S Value
-More Info
Private Name Tags
ContractCreator
GENESIS at txn GENESIS_fc00face00000000000000000000000000000001
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Genesis Bytecode Match Only)
Contract Name:
SFC
Compiler Version
v0.8.27+commit.40a35a09
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {Decimal} from "../common/Decimal.sol"; import {NodeDriverAuth} from "./NodeDriverAuth.sol"; import {ConstantsManager} from "./ConstantsManager.sol"; import {Version} from "../version/Version.sol"; /** * @title Special Fee Contract for Sonic network * @notice The SFC maintains a list of validators and delegators and distributes rewards to them. * @custom:security-contact [email protected] */ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version { uint256 internal constant OK_STATUS = 0; uint256 internal constant WITHDRAWN_BIT = 1; uint256 internal constant OFFLINE_BIT = 1 << 3; uint256 internal constant OFFLINE_AVG_BIT = 1 << 4; uint256 internal constant DOUBLESIGN_BIT = 1 << 7; uint256 internal constant CHEATER_MASK = DOUBLESIGN_BIT; /** * @dev The staking for validation */ struct Validator { uint256 status; uint256 receivedStake; // from all delegators (weight of the validator) address auth; // self-stake delegator uint256 createdEpoch; uint256 createdTime; uint256 deactivatedTime; uint256 deactivatedEpoch; } NodeDriverAuth internal node; // last sealed epoch (currentEpoch - 1) uint256 public currentSealedEpoch; mapping(uint256 validatorID => Validator) public getValidator; mapping(address auth => uint256 validatorID) public getValidatorID; mapping(uint256 validatorID => bytes pubkey) public getValidatorPubkey; uint256 public lastValidatorID; // total stake of all validators - includes slashed/offline validators uint256 public totalStake; // total stake of active (OK_STATUS) validators (total weight) uint256 public totalActiveStake; // unresolved fees that failed to be send to the treasury uint256 public unresolvedTreasuryFees; // delegator => validator ID => stashed rewards (to be claimed/restaked) mapping(address delegator => mapping(uint256 validatorID => uint256 stashedRewards)) internal _rewardsStash; // delegator => validator ID => last epoch number for which were rewards stashed mapping(address delegator => mapping(uint256 validatorID => uint256 epoch)) public stashedRewardsUntilEpoch; struct WithdrawalRequest { uint256 epoch; // epoch where undelegated uint256 time; // when undelegated uint256 amount; } // delegator => validator ID => withdrawal ID => withdrawal request mapping(address delegator => mapping(uint256 validatorID => mapping(uint256 wrID => WithdrawalRequest))) public getWithdrawalRequest; // delegator => validator ID => current stake mapping(address delegator => mapping(uint256 validatorID => uint256 stake)) public getStake; // data structure to compute average uptime for each active validator struct AverageUptime { // average uptime ratio as a value between 0 and 1e18 uint64 averageUptime; // remainder from the division in the average calculation uint32 remainder; // number of epochs in the average (at most averageUptimeEpochsWindow) uint32 epochs; } struct EpochSnapshot { // validator ID => validator weight in the epoch mapping(uint256 => uint256) receivedStake; // validator ID => accumulated ( delegatorsReward * 1e18 / receivedStake ) mapping(uint256 => uint256) accumulatedRewardPerToken; // validator ID => accumulated online time mapping(uint256 => uint256) accumulatedUptime; // validator ID => average uptime as a percentage mapping(uint256 => AverageUptime) averageUptime; // validator ID => gas fees from txs originated by the validator mapping(uint256 => uint256) accumulatedOriginatedTxsFee; mapping(uint256 => uint256) offlineTime; mapping(uint256 => uint256) offlineBlocks; uint256[] validatorIDs; uint256 endTime; uint256 endBlock; uint256 epochFee; // gas fees from txs in the epoch uint256 baseRewardPerSecond; // the base reward to divide among validators for each second of the epoch uint256 totalStake; // total weight of all validators uint256 totalSupply; // total supply of native tokens } // the total supply of native tokens in the chain uint256 public totalSupply; // epoch id => epoch snapshot mapping(uint256 epoch => EpochSnapshot) public getEpochSnapshot; // validator ID -> slashing refund ratio (allows to withdraw slashed stake) mapping(uint256 validatorID => uint256 refundRatio) public slashingRefundRatio; // the treasure contract (receives unlock penalties and a part of epoch fees) address public treasuryAddress; ConstantsManager internal c; // the contract subscribed to stake changes notifications address public stakeSubscriberAddress; // address derived from the validator pubkey => validator id mapping(address pubkeyAddress => uint256 validatorID) public pubkeyAddressToValidatorID; // address authorized to initiate redirection address public redirectionAuthorizer; // delegator => withdrawals receiver mapping(address delegator => address receiver) public getRedirectionRequest; // delegator => withdrawals receiver mapping(address delegator => address receiver) public getRedirection; struct SealEpochRewardsCtx { uint256[] baseRewardWeights; uint256 totalBaseRewardWeight; uint256[] txRewardWeights; uint256 totalTxRewardWeight; uint256 epochFee; } // auth error NotDriverAuth(); error NotAuthorized(); // addresses error ZeroAddress(); error SameAddress(); // values error ZeroAmount(); error ZeroRewards(); // pubkeys error PubkeyUsedByOtherValidator(); error MalformedPubkey(); // redirections error AlreadyRedirected(); error SameRedirectionAuthorizer(); error Redirected(); // validators error ValidatorNotExists(); error ValidatorExists(); error ValidatorNotActive(); error ValidatorDelegationLimitExceeded(); error NotDeactivatedStatus(); // requests error RequestExists(); error RequestNotExists(); // transfers error TransfersNotAllowed(); error TransferFailed(); // stake changes subscriber error StakeSubscriberFailed(); // staking error InsufficientSelfStake(); error NotEnoughTimePassed(); error NotEnoughEpochsPassed(); error StakeIsFullySlashed(); // stashing error NothingToStash(); // slashing error ValidatorNotSlashed(); error RefundRatioTooHigh(); // treasury error TreasuryNotSet(); error NoUnresolvedTreasuryFees(); event DeactivatedValidator(uint256 indexed validatorID, uint256 deactivatedEpoch, uint256 deactivatedTime); event ChangedValidatorStatus(uint256 indexed validatorID, uint256 status); event CreatedValidator( uint256 indexed validatorID, address indexed auth, uint256 createdEpoch, uint256 createdTime ); event Delegated(address indexed delegator, uint256 indexed toValidatorID, uint256 amount); event Undelegated(address indexed delegator, uint256 indexed toValidatorID, uint256 indexed wrID, uint256 amount); event Withdrawn( address indexed delegator, uint256 indexed toValidatorID, uint256 indexed wrID, uint256 amount, uint256 penalty ); event ClaimedRewards(address indexed delegator, uint256 indexed toValidatorID, uint256 rewards); event RestakedRewards(address indexed delegator, uint256 indexed toValidatorID, uint256 rewards); event BurntFTM(uint256 amount); event UpdatedSlashingRefundRatio(uint256 indexed validatorID, uint256 refundRatio); event RefundedSlashedLegacyDelegation(address indexed delegator, uint256 indexed validatorID, uint256 amount); event AnnouncedRedirection(address indexed from, address indexed to); event TreasuryFeesResolved(uint256 amount); modifier onlyDriver() { if (!isNode(msg.sender)) { revert NotDriverAuth(); } _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// Initialization is called only once, after the contract deployment. /// Because the contract code is written directly into genesis, constructor cannot be used. function initialize( uint256 sealedEpoch, uint256 _totalSupply, address nodeDriver, address _c, address owner ) external initializer { __Ownable_init(owner); __UUPSUpgradeable_init(); currentSealedEpoch = sealedEpoch; node = NodeDriverAuth(nodeDriver); c = ConstantsManager(_c); totalSupply = _totalSupply; getEpochSnapshot[sealedEpoch].endTime = _now(); } /// Override the upgrade authorization check to allow upgrades only from the owner. // solhint-disable-next-line no-empty-blocks function _authorizeUpgrade(address) internal override onlyOwner {} /// Receive fallback to revert transfers. receive() external payable { revert TransfersNotAllowed(); } /// Set admin address responsible for initiating redirections. function setRedirectionAuthorizer(address v) external onlyOwner { if (redirectionAuthorizer == v) { revert SameRedirectionAuthorizer(); } redirectionAuthorizer = v; } /// Announce redirection of address to be called by validator whose auth key was compromised. /// Produced events are used to notify redirect authorizer about redirection request. /// Redirect authorizer then initiates creating of appropriate redirect by calling initiateRedirection(). function announceRedirection(address to) external { emit AnnouncedRedirection(msg.sender, to); } /// Initiate redirection of withdrawals/claims for a compromised validator account. /// Needs to be accepted by validator key holder before the redirect is active. function initiateRedirection(address from, address to) external { if (msg.sender != redirectionAuthorizer) { revert NotAuthorized(); } if (getRedirection[from] == to) { revert AlreadyRedirected(); } if (from == to) { revert SameAddress(); } getRedirectionRequest[from] = to; } /// Accept redirection proposal. /// Redirection must by accepted by the validator key holder before it start to be applied. function redirect(address to) external { address from = msg.sender; if (to == address(0)) { revert ZeroAddress(); } if (getRedirectionRequest[from] != to) { revert RequestNotExists(); } getRedirection[from] = to; getRedirectionRequest[from] = address(0); } /// Seal current epoch - deactivate validators who were offline too long, create an epoch snapshot /// for the current epoch (provides information for rewards calculation), calculate new minimal gas price. /// This method is called BEFORE the epoch sealing made by the client itself. function sealEpoch( uint256[] calldata offlineTime, uint256[] calldata offlineBlocks, uint256[] calldata uptimes, uint256[] calldata originatedTxsFee ) external onlyDriver { EpochSnapshot storage snapshot = getEpochSnapshot[currentEpoch()]; uint256[] memory validatorIDs = snapshot.validatorIDs; _sealEpochOffline(snapshot, validatorIDs, offlineTime, offlineBlocks); { EpochSnapshot storage prevSnapshot = getEpochSnapshot[currentSealedEpoch]; uint256 epochDuration = 1; if (_now() > prevSnapshot.endTime) { epochDuration = _now() - prevSnapshot.endTime; } _sealEpochRewards(epochDuration, snapshot, prevSnapshot, validatorIDs, uptimes, originatedTxsFee); _sealEpochAverageUptime(epochDuration, snapshot, prevSnapshot, validatorIDs, uptimes); } currentSealedEpoch = currentEpoch(); snapshot.endTime = _now(); snapshot.endBlock = block.number; snapshot.baseRewardPerSecond = c.baseRewardPerSecond(); snapshot.totalSupply = totalSupply; } /// Finish epoch sealing - store validators of the new epoch into a snapshot. /// This method is called AFTER the epoch sealing made by the client itself. function sealEpochValidators(uint256[] calldata nextValidatorIDs) external onlyDriver { EpochSnapshot storage snapshot = getEpochSnapshot[currentEpoch()]; // fill data for the next snapshot for (uint256 i = 0; i < nextValidatorIDs.length; i++) { uint256 validatorID = nextValidatorIDs[i]; uint256 receivedStake = getValidator[validatorID].receivedStake; snapshot.receivedStake[validatorID] = receivedStake; snapshot.totalStake = snapshot.totalStake + receivedStake; } snapshot.validatorIDs = nextValidatorIDs; } /// Set an initial validator. /// Called only as part of network initialization/genesis file generating. function setGenesisValidator( address auth, uint256 validatorID, bytes calldata pubkey, uint256 createdTime ) external onlyDriver { _rawCreateValidator( auth, validatorID, pubkey, OK_STATUS, 0, // createdEpoch createdTime, 0, // deactivatedEpoch - not deactivated 0 // deactivatedTime - not deactivated ); if (validatorID > lastValidatorID) { lastValidatorID = validatorID; } } /// Set an initial delegation. /// Called only as part of network initialization/genesis file generating. function setGenesisDelegation(address delegator, uint256 toValidatorID, uint256 stake) external onlyDriver { _rawDelegate(delegator, toValidatorID, stake, false); _mintNativeToken(stake); } /// Create a validator with a given public key while using attached value as the validator's self-stake. function createValidator(bytes calldata pubkey) external payable { if (msg.value < c.minSelfStake()) { revert InsufficientSelfStake(); } if (pubkey.length != 66 || pubkey[0] != 0xc0) { revert MalformedPubkey(); } if (pubkeyAddressToValidatorID[_pubkeyToAddress(pubkey)] != 0) { revert PubkeyUsedByOtherValidator(); } _createValidator(msg.sender, pubkey); _delegate(msg.sender, lastValidatorID, msg.value); } /// Update slashing refund ratio for a validator. /// The refund ratio is used to calculate the amount of stake that can be withdrawn after slashing. function updateSlashingRefundRatio(uint256 validatorID, uint256 refundRatio) external onlyOwner { if (!isSlashed(validatorID)) { revert ValidatorNotSlashed(); } if (refundRatio > Decimal.unit()) { revert RefundRatioTooHigh(); } slashingRefundRatio[validatorID] = refundRatio; emit UpdatedSlashingRefundRatio(validatorID, refundRatio); } /// Delegate stake to a validator. function delegate(uint256 toValidatorID) external payable { _delegate(msg.sender, toValidatorID, msg.value); } /// Withdraw stake from a validator after its un-delegation. /// Un-delegated stake is locked for a certain period of time. function withdraw(uint256 toValidatorID, uint256 wrID) public { _withdraw(msg.sender, toValidatorID, wrID, _receiverOf(msg.sender)); } /// Deactivate a validator. /// Called by the chain client when a client misbehavior is observed. function deactivateValidator(uint256 validatorID, uint256 status) external onlyDriver { if (status == OK_STATUS) { revert NotDeactivatedStatus(); } _setValidatorDeactivated(validatorID, status); _syncValidator(validatorID, false); address validatorAddr = getValidator[validatorID].auth; _notifyStakeSubscriber(validatorAddr, validatorAddr, false); } /// Stash rewards for a delegator. function stashRewards(address delegator, uint256 toValidatorID) external { if (!_stashRewards(delegator, toValidatorID)) { revert NothingToStash(); } } /// Resolve failed treasury transfers and send the unresolved fees to the treasury address. function resolveTreasuryFees() external { if (treasuryAddress == address(0)) { revert TreasuryNotSet(); } if (unresolvedTreasuryFees == 0) { revert NoUnresolvedTreasuryFees(); } // zero the fees before sending to prevent re-entrancy uint256 fees = unresolvedTreasuryFees; unresolvedTreasuryFees = 0; (bool success, ) = treasuryAddress.call{value: fees, gas: 1000000}(""); if (!success) { revert TransferFailed(); } emit TreasuryFeesResolved(fees); } /// burnFTM allows SFC to burn an arbitrary amount of FTM tokens. function burnFTM(uint256 amount) external onlyOwner { _burnFTM(amount); } /// Issue tokens to the issued tokens recipient as a counterparty to the burnt FTM tokens. function issueTokens(uint256 amount) external onlyOwner { if (c.issuedTokensRecipient() == address(0)) { revert ZeroAddress(); } node.incBalance(c.issuedTokensRecipient(), amount); totalSupply += amount; } /// Update treasury address. function updateTreasuryAddress(address v) external onlyOwner { treasuryAddress = v; } /// Update consts address. function updateConstsAddress(address v) external onlyOwner { c = ConstantsManager(v); } /// Update voteBook address. function updateStakeSubscriberAddress(address v) external onlyOwner { stakeSubscriberAddress = v; } /// Get consts address. function constsAddress() external view returns (address) { return address(c); } /// Claim rewards for stake delegated to a validator. function claimRewards(uint256 toValidatorID) public { address delegator = msg.sender; uint256 rewards = _claimRewards(delegator, toValidatorID); // It's important that we transfer after erasing (protection against Re-Entrancy) (bool sent, ) = _receiverOf(delegator).call{value: rewards}(""); if (!sent) { revert TransferFailed(); } emit ClaimedRewards(delegator, toValidatorID, rewards); } /// Get amount of currently stashed rewards. function rewardsStash(address delegator, uint256 validatorID) public view returns (uint256) { return _rewardsStash[delegator][validatorID]; } /// Un-delegate stake from a validator. function undelegate(uint256 toValidatorID, uint256 wrID, uint256 amount) public { address delegator = msg.sender; _stashRewards(delegator, toValidatorID); if (amount == 0) { revert ZeroAmount(); } if (getWithdrawalRequest[delegator][toValidatorID][wrID].amount != 0) { revert RequestExists(); } _rawUndelegate(delegator, toValidatorID, amount, true, false, true); getWithdrawalRequest[delegator][toValidatorID][wrID].amount = amount; getWithdrawalRequest[delegator][toValidatorID][wrID].epoch = currentEpoch(); getWithdrawalRequest[delegator][toValidatorID][wrID].time = _now(); _syncValidator(toValidatorID, false); emit Undelegated(delegator, toValidatorID, wrID, amount); } /// Re-stake rewards - claim rewards for staking and delegate it immediately /// to the same validator - add it to the current stake. function restakeRewards(uint256 toValidatorID) public { address delegator = msg.sender; uint256 rewards = _claimRewards(delegator, toValidatorID); _delegate(delegator, toValidatorID, rewards); emit RestakedRewards(delegator, toValidatorID, rewards); } /// Get the current epoch number. function currentEpoch() public view returns (uint256) { return currentSealedEpoch + 1; } /// Get self-stake of a validator. function getSelfStake(uint256 validatorID) public view returns (uint256) { return getStake[getValidator[validatorID].auth][validatorID]; } /// Get validator IDs for given epoch. function getEpochValidatorIDs(uint256 epoch) public view returns (uint256[] memory) { return getEpochSnapshot[epoch].validatorIDs; } /// Get received stake for a validator in a given epoch. function getEpochReceivedStake(uint256 epoch, uint256 validatorID) public view returns (uint256) { return getEpochSnapshot[epoch].receivedStake[validatorID]; } /// Get accumulated reward per token for a validator in a given epoch. function getEpochAccumulatedRewardPerToken(uint256 epoch, uint256 validatorID) public view returns (uint256) { return getEpochSnapshot[epoch].accumulatedRewardPerToken[validatorID]; } /// Get accumulated uptime for a validator in a given epoch. function getEpochAccumulatedUptime(uint256 epoch, uint256 validatorID) public view returns (uint256) { return getEpochSnapshot[epoch].accumulatedUptime[validatorID]; } /// Get average uptime for a validator in a given epoch. function getEpochAverageUptime(uint256 epoch, uint256 validatorID) public view returns (uint64) { return getEpochSnapshot[epoch].averageUptime[validatorID].averageUptime; } /// Get accumulated originated txs fee for a validator in a given epoch. function getEpochAccumulatedOriginatedTxsFee(uint256 epoch, uint256 validatorID) public view returns (uint256) { return getEpochSnapshot[epoch].accumulatedOriginatedTxsFee[validatorID]; } /// Get offline time for a validator in a given epoch. function getEpochOfflineTime(uint256 epoch, uint256 validatorID) public view returns (uint256) { return getEpochSnapshot[epoch].offlineTime[validatorID]; } /// Get offline blocks for a validator in a given epoch. function getEpochOfflineBlocks(uint256 epoch, uint256 validatorID) public view returns (uint256) { return getEpochSnapshot[epoch].offlineBlocks[validatorID]; } /// Get end block for a given epoch. function getEpochEndBlock(uint256 epoch) public view returns (uint256) { return getEpochSnapshot[epoch].endBlock; } /// Check whether the given validator is slashed - the stake (or its part) cannot /// be withdrawn because of misbehavior (double-sign) of the validator. function isSlashed(uint256 validatorID) public view returns (bool) { return getValidator[validatorID].status & CHEATER_MASK != 0; } /// Get the amount of rewards which can be currently claimed by the given delegator for the given validator. function pendingRewards(address delegator, uint256 toValidatorID) public view returns (uint256) { uint256 reward = _newRewards(delegator, toValidatorID); return _rewardsStash[delegator][toValidatorID] + reward; } /// Check whether the self-stake covers the required fraction of all delegations for the given validator. function _checkDelegatedStakeLimit(uint256 validatorID) internal view returns (bool) { return getValidator[validatorID].receivedStake <= (getSelfStake(validatorID) * c.maxDelegatedRatio()) / Decimal.unit(); } /// Check if an address is the NodeDriverAuth contract. function isNode(address addr) internal view virtual returns (bool) { return addr == address(node); } /// Delegate stake to a validator. function _delegate(address delegator, uint256 toValidatorID, uint256 amount) internal { if (!_validatorExists(toValidatorID)) { revert ValidatorNotExists(); } if (getValidator[toValidatorID].status != OK_STATUS) { revert ValidatorNotActive(); } _rawDelegate(delegator, toValidatorID, amount, true); if (!_checkDelegatedStakeLimit(toValidatorID)) { revert ValidatorDelegationLimitExceeded(); } } /// Delegate stake to a validator without checking delegation limit. function _rawDelegate(address delegator, uint256 toValidatorID, uint256 amount, bool strict) internal { if (amount == 0) { revert ZeroAmount(); } _stashRewards(delegator, toValidatorID); getStake[delegator][toValidatorID] = getStake[delegator][toValidatorID] + amount; uint256 origStake = getValidator[toValidatorID].receivedStake; getValidator[toValidatorID].receivedStake = origStake + amount; totalStake = totalStake + amount; if (getValidator[toValidatorID].status == OK_STATUS) { totalActiveStake = totalActiveStake + amount; } _syncValidator(toValidatorID, origStake == 0); emit Delegated(delegator, toValidatorID, amount); _notifyStakeSubscriber(delegator, getValidator[toValidatorID].auth, strict); } /// Un-delegate stake from a validator. function _rawUndelegate( address delegator, uint256 toValidatorID, uint256 amount, bool strict, bool forceful, bool checkDelegatedStake ) internal { getStake[delegator][toValidatorID] -= amount; getValidator[toValidatorID].receivedStake = getValidator[toValidatorID].receivedStake - amount; totalStake = totalStake - amount; if (getValidator[toValidatorID].status == OK_STATUS) { totalActiveStake = totalActiveStake - amount; } uint256 selfStakeAfterwards = getSelfStake(toValidatorID); if (selfStakeAfterwards != 0 && getValidator[toValidatorID].status == OK_STATUS) { if (!(selfStakeAfterwards >= c.minSelfStake())) { if (forceful) { revert InsufficientSelfStake(); } else { _setValidatorDeactivated(toValidatorID, WITHDRAWN_BIT); } } if (checkDelegatedStake && !_checkDelegatedStakeLimit(toValidatorID)) { revert ValidatorDelegationLimitExceeded(); } } else { _setValidatorDeactivated(toValidatorID, WITHDRAWN_BIT); } _notifyStakeSubscriber(delegator, getValidator[toValidatorID].auth, strict); } /// Get slashing penalty for a stake. function getSlashingPenalty( uint256 amount, bool isCheater, uint256 refundRatio ) internal pure returns (uint256 penalty) { if (!isCheater || refundRatio >= Decimal.unit()) { return 0; } // round penalty upwards (ceiling) to prevent dust amount attacks penalty = (amount * (Decimal.unit() - refundRatio)) / Decimal.unit() + 1; if (penalty > amount) { return amount; } return penalty; } /// Withdraw stake from a validator. /// The stake must be undelegated first. function _withdraw(address delegator, uint256 toValidatorID, uint256 wrID, address payable receiver) private { WithdrawalRequest memory request = getWithdrawalRequest[delegator][toValidatorID][wrID]; if (request.epoch == 0) { revert RequestNotExists(); } uint256 requestTime = request.time; uint256 requestEpoch = request.epoch; if ( getValidator[toValidatorID].deactivatedTime != 0 && getValidator[toValidatorID].deactivatedTime < requestTime ) { requestTime = getValidator[toValidatorID].deactivatedTime; requestEpoch = getValidator[toValidatorID].deactivatedEpoch; } if (_now() < requestTime + c.withdrawalPeriodTime()) { revert NotEnoughTimePassed(); } if (currentEpoch() < requestEpoch + c.withdrawalPeriodEpochs()) { revert NotEnoughEpochsPassed(); } uint256 amount = getWithdrawalRequest[delegator][toValidatorID][wrID].amount; bool isCheater = isSlashed(toValidatorID); uint256 penalty = getSlashingPenalty(amount, isCheater, slashingRefundRatio[toValidatorID]); delete getWithdrawalRequest[delegator][toValidatorID][wrID]; if (amount <= penalty) { revert StakeIsFullySlashed(); } // It's important that we transfer after erasing (protection against Re-Entrancy) (bool sent, ) = receiver.call{value: amount - penalty}(""); if (!sent) { revert TransferFailed(); } _burnFTM(penalty); emit Withdrawn(delegator, toValidatorID, wrID, amount - penalty, penalty); } /// Get highest epoch for which can be claimed rewards for the given validator. // If the validator is deactivated, the highest payable epoch is the deactivation epoch // or the current epoch, whichever is lower function _highestPayableEpoch(uint256 validatorID) internal view returns (uint256) { if (getValidator[validatorID].deactivatedEpoch != 0) { if (currentSealedEpoch < getValidator[validatorID].deactivatedEpoch) { return currentSealedEpoch; } return getValidator[validatorID].deactivatedEpoch; } return currentSealedEpoch; } /// Get new rewards for a delegator. /// The rewards are calculated from the last stashed epoch until the highest payable epoch. function _newRewards(address delegator, uint256 toValidatorID) internal view returns (uint256) { uint256 stashedUntil = stashedRewardsUntilEpoch[delegator][toValidatorID]; uint256 payableUntil = _highestPayableEpoch(toValidatorID); uint256 wholeStake = getStake[delegator][toValidatorID]; uint256 fullReward = _newRewardsOf(wholeStake, toValidatorID, stashedUntil, payableUntil); return fullReward; } /// Get new rewards for a delegator for a given stake amount and epoch range. function _newRewardsOf( uint256 stakeAmount, uint256 toValidatorID, uint256 fromEpoch, uint256 toEpoch ) internal view returns (uint256) { if (fromEpoch >= toEpoch) { return 0; } uint256 stashedRate = getEpochSnapshot[fromEpoch].accumulatedRewardPerToken[toValidatorID]; uint256 currentRate = getEpochSnapshot[toEpoch].accumulatedRewardPerToken[toValidatorID]; return ((currentRate - stashedRate) * stakeAmount) / Decimal.unit(); } /// Stash rewards for a delegator. function _stashRewards(address delegator, uint256 toValidatorID) internal returns (bool updated) { uint256 nonStashedReward = _newRewards(delegator, toValidatorID); stashedRewardsUntilEpoch[delegator][toValidatorID] = _highestPayableEpoch(toValidatorID); _rewardsStash[delegator][toValidatorID] += nonStashedReward; return nonStashedReward != 0; } /// Claim rewards for a delegator. function _claimRewards(address delegator, uint256 toValidatorID) internal returns (uint256) { _stashRewards(delegator, toValidatorID); uint256 rewards = _rewardsStash[delegator][toValidatorID]; if (rewards == 0) { revert ZeroRewards(); } delete _rewardsStash[delegator][toValidatorID]; // It's important that we mint after erasing (protection against Re-Entrancy) _mintNativeToken(rewards); return rewards; } /// Burn FTM tokens. /// The tokens are sent to the zero address. function _burnFTM(uint256 amount) internal { if (amount != 0) { payable(address(0)).transfer(amount); emit BurntFTM(amount); } } /// Get epoch end time. function epochEndTime(uint256 epoch) internal view returns (uint256) { return getEpochSnapshot[epoch].endTime; } /// Check if an address is redirected. function _redirected(address addr) internal view returns (bool) { return getRedirection[addr] != address(0); } /// Get address which should receive rewards and withdrawn stake for the given delegator. /// The delegator is usually the receiver, unless a redirection is created. function _receiverOf(address addr) internal view returns (address payable) { address to = getRedirection[addr]; if (to == address(0)) { return payable(address(uint160(addr))); } return payable(address(uint160(to))); } /// Seal epoch - sync validators. function _sealEpochOffline( EpochSnapshot storage snapshot, uint256[] memory validatorIDs, uint256[] memory offlineTime, uint256[] memory offlineBlocks ) internal { // mark offline nodes for (uint256 i = 0; i < validatorIDs.length; i++) { if ( offlineBlocks[i] > c.offlinePenaltyThresholdBlocksNum() && offlineTime[i] >= c.offlinePenaltyThresholdTime() ) { _setValidatorDeactivated(validatorIDs[i], OFFLINE_BIT); _syncValidator(validatorIDs[i], false); } // log data snapshot.offlineTime[validatorIDs[i]] = offlineTime[i]; snapshot.offlineBlocks[validatorIDs[i]] = offlineBlocks[i]; } } /// Seal epoch - calculate rewards. function _sealEpochRewards( uint256 epochDuration, EpochSnapshot storage snapshot, EpochSnapshot storage prevSnapshot, uint256[] memory validatorIDs, uint256[] memory uptimes, uint256[] memory accumulatedOriginatedTxsFee ) internal { SealEpochRewardsCtx memory ctx = SealEpochRewardsCtx( new uint256[](validatorIDs.length), 0, new uint256[](validatorIDs.length), 0, 0 ); for (uint256 i = 0; i < validatorIDs.length; i++) { uint256 prevAccumulatedTxsFee = prevSnapshot.accumulatedOriginatedTxsFee[validatorIDs[i]]; uint256 originatedTxsFee = 0; if (accumulatedOriginatedTxsFee[i] > prevAccumulatedTxsFee) { originatedTxsFee = accumulatedOriginatedTxsFee[i] - prevAccumulatedTxsFee; } // txRewardWeight = {originatedTxsFee} * {uptime} // originatedTxsFee is roughly proportional to {uptime} * {stake}, so the whole formula is roughly // {stake} * {uptime} ^ 2 ctx.txRewardWeights[i] = (originatedTxsFee * uptimes[i]) / epochDuration; ctx.totalTxRewardWeight = ctx.totalTxRewardWeight + ctx.txRewardWeights[i]; ctx.epochFee = ctx.epochFee + originatedTxsFee; } for (uint256 i = 0; i < validatorIDs.length; i++) { // baseRewardWeight = {stake} * {uptime ^ 2} ctx.baseRewardWeights[i] = (((snapshot.receivedStake[validatorIDs[i]] * uptimes[i]) / epochDuration) * uptimes[i]) / epochDuration; ctx.totalBaseRewardWeight = ctx.totalBaseRewardWeight + ctx.baseRewardWeights[i]; } for (uint256 i = 0; i < validatorIDs.length; i++) { uint256 rawReward = _calcRawValidatorEpochBaseReward( epochDuration, c.baseRewardPerSecond(), ctx.baseRewardWeights[i], ctx.totalBaseRewardWeight ); rawReward = rawReward + _calcRawValidatorEpochTxReward(ctx.epochFee, ctx.txRewardWeights[i], ctx.totalTxRewardWeight); uint256 validatorID = validatorIDs[i]; address validatorAddr = getValidator[validatorID].auth; // accounting validator's commission uint256 commissionRewardFull = _calcValidatorCommission(rawReward, c.validatorCommission()); uint256 selfStake = getStake[validatorAddr][validatorID]; if (selfStake != 0) { _rewardsStash[validatorAddr][validatorID] += commissionRewardFull; } // accounting reward per token for delegators uint256 delegatorsReward = rawReward - commissionRewardFull; // note: use latest stake for the sake of rewards distribution accuracy, not snapshot.receivedStake uint256 receivedStake = getValidator[validatorID].receivedStake; uint256 rewardPerToken = 0; if (receivedStake != 0) { rewardPerToken = (delegatorsReward * Decimal.unit()) / receivedStake; } snapshot.accumulatedRewardPerToken[validatorID] = prevSnapshot.accumulatedRewardPerToken[validatorID] + rewardPerToken; snapshot.accumulatedOriginatedTxsFee[validatorID] = accumulatedOriginatedTxsFee[i]; snapshot.accumulatedUptime[validatorID] = prevSnapshot.accumulatedUptime[validatorID] + uptimes[i]; } snapshot.epochFee = ctx.epochFee; if (totalSupply > snapshot.epochFee) { totalSupply -= snapshot.epochFee; } else { totalSupply = 0; } // transfer 10% of fees to treasury if (treasuryAddress != address(0)) { uint256 feeShare = (ctx.epochFee * c.treasuryFeeShare()) / Decimal.unit(); _mintNativeToken(feeShare); (bool success, ) = treasuryAddress.call{value: feeShare, gas: 1000000}(""); // solhint-disable-next-line no-empty-blocks if (!success) { // ignore treasury transfer failure // the treasury failure must not endanger the epoch sealing // store the unresolved treasury fees to be resolved later unresolvedTreasuryFees += feeShare; } } } /// Seal epoch - recalculate average uptime time of validators function _sealEpochAverageUptime( uint256 epochDuration, EpochSnapshot storage snapshot, EpochSnapshot storage prevSnapshot, uint256[] memory validatorIDs, uint256[] memory uptimes ) internal { for (uint256 i = 0; i < validatorIDs.length; i++) { uint256 validatorID = validatorIDs[i]; // compute normalised uptime as a percentage in the fixed-point format uint256 normalisedUptime = (uptimes[i] * Decimal.unit()) / epochDuration; if (normalisedUptime > Decimal.unit()) { normalisedUptime = Decimal.unit(); } AverageUptime memory previous = prevSnapshot.averageUptime[validatorID]; AverageUptime memory current = _addElementIntoAverageUptime(uint64(normalisedUptime), previous); snapshot.averageUptime[validatorID] = current; // remove validator if average uptime drops below min average uptime // (by setting minAverageUptime to zero, this check is ignored) if (current.averageUptime < c.minAverageUptime() && current.epochs >= c.averageUptimeEpochWindow()) { _setValidatorDeactivated(validatorID, OFFLINE_AVG_BIT); _syncValidator(validatorID, false); } } } function _addElementIntoAverageUptime( uint64 newValue, AverageUptime memory prev ) private view returns (AverageUptime memory) { AverageUptime memory cur; if (prev.epochs == 0) { cur.averageUptime = newValue; // the only element for the average cur.epochs = 1; return cur; } // the number of elements the average is calculated from uint128 n = prev.epochs + 1; // add new value into the average uint128 tmp = (n - 1) * uint128(prev.averageUptime) + uint128(newValue) + prev.remainder; cur.averageUptime = uint64(tmp / n); cur.remainder = uint32(tmp % n); if (cur.averageUptime > Decimal.unit()) { cur.averageUptime = uint64(Decimal.unit()); } if (prev.epochs < c.averageUptimeEpochWindow()) { cur.epochs = prev.epochs + 1; } else { cur.epochs = prev.epochs; } return cur; } /// Create a new validator. function _createValidator(address auth, bytes calldata pubkey) internal { uint256 validatorID = ++lastValidatorID; _rawCreateValidator(auth, validatorID, pubkey, OK_STATUS, currentEpoch(), _now(), 0, 0); } /// Create a new validator without incrementing lastValidatorID. function _rawCreateValidator( address auth, uint256 validatorID, bytes calldata pubkey, uint256 status, uint256 createdEpoch, uint256 createdTime, uint256 deactivatedEpoch, uint256 deactivatedTime ) internal { if (getValidatorID[auth] != 0) { revert ValidatorExists(); } getValidatorID[auth] = validatorID; getValidator[validatorID].status = status; getValidator[validatorID].createdEpoch = createdEpoch; getValidator[validatorID].createdTime = createdTime; getValidator[validatorID].deactivatedTime = deactivatedTime; getValidator[validatorID].deactivatedEpoch = deactivatedEpoch; getValidator[validatorID].auth = auth; getValidatorPubkey[validatorID] = pubkey; pubkeyAddressToValidatorID[_pubkeyToAddress(pubkey)] = validatorID; emit CreatedValidator(validatorID, auth, createdEpoch, createdTime); if (deactivatedEpoch != 0) { emit DeactivatedValidator(validatorID, deactivatedEpoch, deactivatedTime); } if (status != 0) { emit ChangedValidatorStatus(validatorID, status); } } /// Calculate raw validator epoch transaction reward. function _calcRawValidatorEpochTxReward( uint256 epochFee, uint256 txRewardWeight, uint256 totalTxRewardWeight ) internal view returns (uint256) { if (txRewardWeight == 0) { return 0; } uint256 txReward = (epochFee * txRewardWeight) / totalTxRewardWeight; // fee reward except burntFeeShare and treasuryFeeShare return (txReward * (Decimal.unit() - c.burntFeeShare() - c.treasuryFeeShare())) / Decimal.unit(); } /// Calculate raw validator epoch base reward. function _calcRawValidatorEpochBaseReward( uint256 epochDuration, uint256 _baseRewardPerSecond, uint256 baseRewardWeight, uint256 totalBaseRewardWeight ) internal pure returns (uint256) { if (baseRewardWeight == 0) { return 0; } uint256 totalReward = epochDuration * _baseRewardPerSecond; return (totalReward * baseRewardWeight) / totalBaseRewardWeight; } /// Mint native token. function _mintNativeToken(uint256 amount) internal { // balance will be increased after the transaction is processed node.incBalance(address(this), amount); totalSupply = totalSupply + amount; } /// Notify stake subscriber about staking changes. /// Used to recount votes from delegators in the governance contract. function _notifyStakeSubscriber(address delegator, address validatorAuth, bool strict) internal { if (stakeSubscriberAddress != address(0)) { // Don't allow announceStakeChange to use up all the gas // solhint-disable-next-line avoid-low-level-calls (bool success, ) = stakeSubscriberAddress.call{gas: 8000000}( abi.encodeWithSignature("announceStakeChange(address,address)", delegator, validatorAuth) ); // Don't revert if announceStakeChange failed unless strict mode enabled if (!success && strict) { revert StakeSubscriberFailed(); } } } /// Set validator deactivated status. function _setValidatorDeactivated(uint256 validatorID, uint256 status) internal { if (getValidator[validatorID].status == OK_STATUS && status != OK_STATUS) { totalActiveStake = totalActiveStake - getValidator[validatorID].receivedStake; } // status as a number is proportional to severity if (status > getValidator[validatorID].status) { getValidator[validatorID].status = status; if (getValidator[validatorID].deactivatedEpoch == 0) { getValidator[validatorID].deactivatedEpoch = currentEpoch(); getValidator[validatorID].deactivatedTime = _now(); emit DeactivatedValidator( validatorID, getValidator[validatorID].deactivatedEpoch, getValidator[validatorID].deactivatedTime ); } emit ChangedValidatorStatus(validatorID, status); } } /// Sync validator with node. function _syncValidator(uint256 validatorID, bool syncPubkey) public { if (!_validatorExists(validatorID)) { revert ValidatorNotExists(); } // emit special log for node uint256 weight = getValidator[validatorID].receivedStake; if (getValidator[validatorID].status != OK_STATUS) { weight = 0; } node.updateValidatorWeight(validatorID, weight); if (syncPubkey && weight != 0) { node.updateValidatorPubkey(validatorID, getValidatorPubkey[validatorID]); } } /// Check if a validator exists. function _validatorExists(uint256 validatorID) internal view returns (bool) { return getValidator[validatorID].createdTime != 0; } /// Calculate validator commission. function _calcValidatorCommission(uint256 rawReward, uint256 commission) internal pure returns (uint256) { return (rawReward * commission) / Decimal.unit(); } /// Derive address from validator private key function _pubkeyToAddress(bytes calldata pubkey) private pure returns (address) { return address(uint160(uint256(keccak256(pubkey[2:])))); } /// Get current time. function _now() internal view virtual returns (uint256) { return block.timestamp; } uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.20; import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol"; import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol"; import {Initializable} from "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. */ abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable __self = address(this); /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string. * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function * during an upgrade. */ string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev The call is from an unauthorized context. */ error UUPSUnauthorizedCallContext(); /** * @dev The storage `slot` is unsupported as a UUID. */ error UUPSUnsupportedProxiableUUID(bytes32 slot); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { _checkProxy(); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { _checkNotDelegated(); _; } function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /** * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data); } /** * @dev Reverts if the execution is not performed via delegatecall or the execution * context is not of a proxy with an ERC-1967 compliant implementation pointing to self. * See {_onlyProxy}. */ function _checkProxy() internal view virtual { if ( address(this) == __self || // Must be called through delegatecall ERC1967Utils.getImplementation() != __self // Must be called through an active proxy ) { revert UUPSUnauthorizedCallContext(); } } /** * @dev Reverts if the execution is performed via delegatecall. * See {notDelegated}. */ function _checkNotDelegated() internal view virtual { if (address(this) != __self) { // Must not be called through delegatecall revert UUPSUnauthorizedCallContext(); } } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call. * * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value * is expected to be the implementation slot in ERC-1967. * * Emits an {IERC1967-Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) { revert UUPSUnsupportedProxiableUUID(slot); } ERC1967Utils.upgradeToAndCall(newImplementation, data); } catch { // The implementation is not UUPS revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../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. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.20; /** * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.20; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.20; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.21; import {IBeacon} from "../beacon/IBeacon.sol"; import {IERC1967} from "../../interfaces/IERC1967.sol"; import {Address} from "../../utils/Address.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; /** * @dev This library provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots. */ library ERC1967Utils { /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @dev Returns the current implementation address. */ function getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the ERC-1967 implementation slot. */ function _setImplementation(address newImplementation) private { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit IERC1967.Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(ADMIN_SLOT).value; } /** * @dev Stores a new address in the ERC-1967 admin slot. */ function _setAdmin(address newAdmin) private { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-AdminChanged} event. */ function changeAdmin(address newAdmin) internal { emit IERC1967.AdminChanged(getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the ERC-1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit IERC1967.BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC-1967 implementation slot: * ```solidity * contract ERC1967 { * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * TIP: Consider using this library along with {SlotDerivation}. */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct Int256Slot { int256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Int256Slot` with member `value` located at `slot`. */ function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { r.slot := store.slot } } /** * @dev Returns a `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { r.slot := store.slot } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; /** * @custom:security-contact [email protected] */ library Decimal { // unit is used for decimals, e.g. 0.123456 function unit() internal pure returns (uint256) { return 1e18; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; /** * @title EVM Writer Interface * @notice Allows the NodeDriver contract to write into the state database. * @dev Implemented in the native code of the Sonic client. * @custom:security-contact [email protected] */ interface IEVMWriter { function setBalance(address acc, uint256 value) external; function copyCode(address acc, address from) external; function swapCode(address acc, address where) external; function setStorage(address acc, bytes32 key, bytes32 value) external; function incNonce(address acc, uint256 diff) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; /** * @title Node Driver Contract Interface * @notice Ensures interaction of on-chain contracts with the Sonic client itself. * @dev Methods with onlyNode modifier are called by Sonic internal txs during epoch sealing. * @custom:security-contact [email protected] */ interface INodeDriver { /// Set an initial validator. Called only as part of network initialization/genesis file generating. function setGenesisValidator( address auth, uint256 validatorID, bytes calldata pubkey, uint256 createdTime ) external; /// Set an initial delegation. Called only as part of network initialization/genesis file generating. function setGenesisDelegation(address delegator, uint256 toValidatorID, uint256 stake) external; /// Deactivate a validator. Called by network node when a double-sign of the given validator is registered. /// Is called before sealEpoch() call. function deactivateValidator(uint256 validatorID, uint256 status) external; /// Seal epoch. Called BEFORE epoch sealing made by the client itself. function sealEpoch( uint256[] calldata offlineTimes, uint256[] calldata offlineBlocks, uint256[] calldata uptimes, uint256[] calldata originatedTxsFee ) external; /// Seal epoch. Called AFTER epoch sealing made by the client itself. function sealEpochValidators(uint256[] calldata nextValidatorIDs) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; /** * @title Node Driver Executable * @notice A batch of operations to be executed with NodeDriver permissions. * @notice Contracts implementing this interface should be executed using NodeDriverAuth.execute() or mutExecute(). * @custom:security-contact [email protected] */ interface INodeDriverExecutable { function execute() external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; /** * @title Special Fee Contract for Sonic network * @notice The SFC maintains a list of validators and delegators and distributes rewards to them. * @custom:security-contact [email protected] */ interface ISFC { event CreatedValidator( uint256 indexed validatorID, address indexed auth, uint256 createdEpoch, uint256 createdTime ); event Delegated(address indexed delegator, uint256 indexed toValidatorID, uint256 amount); event Undelegated(address indexed delegator, uint256 indexed toValidatorID, uint256 indexed wrID, uint256 amount); event Withdrawn( address indexed delegator, uint256 indexed toValidatorID, uint256 indexed wrID, uint256 amount, uint256 penalty ); event ClaimedRewards(address indexed delegator, uint256 indexed toValidatorID, uint256 rewards); event RestakedRewards(address indexed delegator, uint256 indexed toValidatorID, uint256 rewards); event BurntFTM(uint256 amount); event UpdatedSlashingRefundRatio(uint256 indexed validatorID, uint256 refundRatio); event RefundedSlashedLegacyDelegation(address indexed delegator, uint256 indexed validatorID, uint256 amount); event DeactivatedValidator(uint256 indexed validatorID, uint256 deactivatedEpoch, uint256 deactivatedTime); event ChangedValidatorStatus(uint256 indexed validatorID, uint256 status); event AnnouncedRedirection(address indexed from, address indexed to); function currentSealedEpoch() external view returns (uint256); function getEpochSnapshot( uint256 ) external view returns ( uint256 endTime, uint256 endBlock, uint256 epochFee, uint256 baseRewardPerSecond, uint256 totalStake, uint256 totalSupply ); function getStake(address, uint256) external view returns (uint256); function getValidator( uint256 ) external view returns ( uint256 status, uint256 receivedStake, address auth, uint256 createdEpoch, uint256 createdTime, uint256 deactivatedTime, uint256 deactivatedEpoch ); function getValidatorID(address) external view returns (uint256); function getValidatorPubkey(uint256) external view returns (bytes memory); function pubkeyAddressToValidatorID(address pubkeyAddress) external view returns (uint256); function getWithdrawalRequest( address, uint256, uint256 ) external view returns (uint256 epoch, uint256 time, uint256 amount); function isOwner() external view returns (bool); function lastValidatorID() external view returns (uint256); function minGasPrice() external view returns (uint256); function owner() external view returns (address); function renounceOwnership() external; function slashingRefundRatio(uint256) external view returns (uint256); function stashedRewardsUntilEpoch(address, uint256) external view returns (uint256); function totalActiveStake() external view returns (uint256); function totalStake() external view returns (uint256); function totalSupply() external view returns (uint256); function transferOwnership(address newOwner) external; function treasuryAddress() external view returns (address); function version() external pure returns (bytes3); function currentEpoch() external view returns (uint256); function updateConstsAddress(address v) external; function constsAddress() external view returns (address); function getEpochValidatorIDs(uint256 epoch) external view returns (uint256[] memory); function getEpochReceivedStake(uint256 epoch, uint256 validatorID) external view returns (uint256); function getEpochAccumulatedRewardPerToken(uint256 epoch, uint256 validatorID) external view returns (uint256); function getEpochAccumulatedUptime(uint256 epoch, uint256 validatorID) external view returns (uint256); function getEpochAverageUptime(uint256 epoch, uint256 validatorID) external view returns (uint32); function getEpochAccumulatedOriginatedTxsFee(uint256 epoch, uint256 validatorID) external view returns (uint256); function getEpochOfflineTime(uint256 epoch, uint256 validatorID) external view returns (uint256); function getEpochOfflineBlocks(uint256 epoch, uint256 validatorID) external view returns (uint256); function getEpochEndBlock(uint256 epoch) external view returns (uint256); function rewardsStash(address delegator, uint256 validatorID) external view returns (uint256); function createValidator(bytes calldata pubkey) external payable; function getSelfStake(uint256 validatorID) external view returns (uint256); function delegate(uint256 toValidatorID) external payable; function undelegate(uint256 toValidatorID, uint256 wrID, uint256 amount) external; function isSlashed(uint256 validatorID) external view returns (bool); function withdraw(uint256 toValidatorID, uint256 wrID) external; function deactivateValidator(uint256 validatorID, uint256 status) external; function pendingRewards(address delegator, uint256 toValidatorID) external view returns (uint256); function stashRewards(address delegator, uint256 toValidatorID) external; function claimRewards(uint256 toValidatorID) external; function restakeRewards(uint256 toValidatorID) external; function updateSlashingRefundRatio(uint256 validatorID, uint256 refundRatio) external; function updateTreasuryAddress(address v) external; function burnFTM(uint256 amount) external; function sealEpoch( uint256[] calldata offlineTime, uint256[] calldata offlineBlocks, uint256[] calldata uptimes, uint256[] calldata originatedTxsFee ) external; function sealEpochValidators(uint256[] calldata nextValidatorIDs) external; function initialize( uint256 sealedEpoch, uint256 _totalSupply, address nodeDriver, address consts, address _owner ) external; function setGenesisValidator( address auth, uint256 validatorID, bytes calldata pubkey, uint256 createdTime ) external; function setGenesisDelegation(address delegator, uint256 toValidatorID, uint256 stake) external; function updateStakeSubscriberAddress(address v) external; function stakeSubscriberAddress() external view returns (address); function setRedirectionAuthorizer(address v) external; function announceRedirection(address to) external; function initiateRedirection(address from, address to) external; function redirect(address to) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {Decimal} from "../common/Decimal.sol"; /** * @custom:security-contact [email protected] */ contract ConstantsManager is Ownable { // Minimum amount of stake for a validator, i.e., 500000 FTM uint256 public minSelfStake; // Maximum ratio of delegations a validator can have, say, 15 times of self-stake uint256 public maxDelegatedRatio; // The commission fee in percentage a validator will get from a delegation, e.g., 15% uint256 public validatorCommission; // The percentage of fees to burn, e.g., 20% uint256 public burntFeeShare; // The percentage of fees to transfer to treasury address, e.g., 10% uint256 public treasuryFeeShare; // the number of epochs that undelegated stake is locked for uint256 public withdrawalPeriodEpochs; // the number of seconds that undelegated stake is locked for uint256 public withdrawalPeriodTime; uint256 public baseRewardPerSecond; uint256 public offlinePenaltyThresholdBlocksNum; uint256 public offlinePenaltyThresholdTime; uint256 public targetGasPowerPerSecond; uint256 public gasPriceBalancingCounterweight; // The number of epochs to calculate the average uptime ratio from, acceptable bound [10, 87600]. // Is also the minimum number of epochs necessary for deactivation of offline validators. uint32 public averageUptimeEpochWindow; // Minimum average uptime ratio in fixed-point format; acceptable bounds [0,0.9]. // Zero to disable validators deactivation by this metric. uint64 public minAverageUptime; // The address of the recipient that receives issued tokens // as a counterparty to the burnt FTM tokens address public issuedTokensRecipient; /** * @dev Given value is too small */ error ValueTooSmall(); /** * @dev Given value is too large */ error ValueTooLarge(); constructor(address owner) Ownable(owner) {} function updateMinSelfStake(uint256 v) external virtual onlyOwner { if (v < 100000 * 1e18) { revert ValueTooSmall(); } if (v > 10000000 * 1e18) { revert ValueTooLarge(); } minSelfStake = v; } function updateMaxDelegatedRatio(uint256 v) external virtual onlyOwner { if (v < Decimal.unit()) { revert ValueTooSmall(); } if (v > 31 * Decimal.unit()) { revert ValueTooLarge(); } maxDelegatedRatio = v; } function updateValidatorCommission(uint256 v) external virtual onlyOwner { if (v > Decimal.unit() / 2) { revert ValueTooLarge(); } validatorCommission = v; } function updateBurntFeeShare(uint256 v) external virtual onlyOwner { if (v > Decimal.unit() / 2) { revert ValueTooLarge(); } burntFeeShare = v; } function updateTreasuryFeeShare(uint256 v) external virtual onlyOwner { if (v > Decimal.unit() / 2) { revert ValueTooLarge(); } treasuryFeeShare = v; } function updateWithdrawalPeriodEpochs(uint256 v) external virtual onlyOwner { if (v < 2) { revert ValueTooSmall(); } if (v > 100) { revert ValueTooLarge(); } withdrawalPeriodEpochs = v; } function updateWithdrawalPeriodTime(uint256 v) external virtual onlyOwner { if (v < 86400) { revert ValueTooSmall(); } if (v > 30 * 86400) { revert ValueTooLarge(); } withdrawalPeriodTime = v; } function updateBaseRewardPerSecond(uint256 v) external virtual onlyOwner { if (v < 0.5 * 1e18) { revert ValueTooSmall(); } if (v > 32 * 1e18) { revert ValueTooLarge(); } baseRewardPerSecond = v; } function updateOfflinePenaltyThresholdTime(uint256 v) external virtual onlyOwner { if (v < 86400) { revert ValueTooSmall(); } if (v > 10 * 86400) { revert ValueTooLarge(); } offlinePenaltyThresholdTime = v; } function updateOfflinePenaltyThresholdBlocksNum(uint256 v) external virtual onlyOwner { if (v < 100) { revert ValueTooSmall(); } if (v > 1000000) { revert ValueTooLarge(); } offlinePenaltyThresholdBlocksNum = v; } function updateTargetGasPowerPerSecond(uint256 v) external virtual onlyOwner { if (v < 1000000) { revert ValueTooSmall(); } if (v > 500000000) { revert ValueTooLarge(); } targetGasPowerPerSecond = v; } function updateGasPriceBalancingCounterweight(uint256 v) external virtual onlyOwner { if (v < 100) { revert ValueTooSmall(); } if (v > 10 * 86400) { revert ValueTooLarge(); } gasPriceBalancingCounterweight = v; } function updateAverageUptimeEpochWindow(uint32 v) external virtual onlyOwner { if (v < 10) { // needs to be long enough to allow permissible downtime for validators maintenance revert ValueTooSmall(); } if (v > 87600) { revert ValueTooLarge(); } averageUptimeEpochWindow = v; } function updateMinAverageUptime(uint64 v) external virtual onlyOwner { if (v > ((Decimal.unit() * 9) / 10)) { revert ValueTooLarge(); } minAverageUptime = v; } function updateIssuedTokensRecipient(address v) external virtual onlyOwner { issuedTokensRecipient = v; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; import {ISFC} from "../interfaces/ISFC.sol"; import {NodeDriver} from "./NodeDriver.sol"; import {NodeDriverAuth} from "./NodeDriverAuth.sol"; import {ConstantsManager} from "./ConstantsManager.sol"; import {Decimal} from "../common/Decimal.sol"; /** * @custom:security-contact [email protected] */ contract NetworkInitializer { // Initialize NodeDriverAuth, NodeDriver and SFC in one call to allow fewer genesis transactions function initializeAll( uint256 sealedEpoch, uint256 totalSupply, address payable _sfc, address _auth, address _driver, address _evmWriter, address _owner ) external { NodeDriver(_driver).initialize(_auth, _evmWriter, _owner); NodeDriverAuth(_auth).initialize(_sfc, _driver, _owner); ConstantsManager consts = new ConstantsManager(address(this)); consts.updateMinSelfStake(500000 * 1e18); consts.updateMaxDelegatedRatio(16 * Decimal.unit()); consts.updateValidatorCommission((15 * Decimal.unit()) / 100); consts.updateBurntFeeShare((20 * Decimal.unit()) / 100); consts.updateTreasuryFeeShare((10 * Decimal.unit()) / 100); consts.updateWithdrawalPeriodEpochs(3); consts.updateWithdrawalPeriodTime(60 * 60 * 24 * 7); consts.updateBaseRewardPerSecond(2668658453701531600); consts.updateOfflinePenaltyThresholdTime(5 days); consts.updateOfflinePenaltyThresholdBlocksNum(1000); consts.updateTargetGasPowerPerSecond(2000000); consts.updateGasPriceBalancingCounterweight(3600); consts.updateAverageUptimeEpochWindow(100); consts.updateMinAverageUptime(0); // check disabled by default consts.transferOwnership(_owner); ISFC(_sfc).initialize(sealedEpoch, totalSupply, _auth, address(consts), _owner); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {NodeDriverAuth} from "./NodeDriverAuth.sol"; import {IEVMWriter} from "../interfaces/IEVMWriter.sol"; import {INodeDriver} from "../interfaces/INodeDriver.sol"; /** * @title Node Driver Contract * @notice Ensures interaction of on-chain contracts with the Sonic client itself. * @dev Methods with onlyNode modifier are called by Sonic internal txs during epoch sealing. * @custom:security-contact [email protected] */ contract NodeDriver is OwnableUpgradeable, UUPSUpgradeable, INodeDriver { NodeDriverAuth internal backend; IEVMWriter internal evmWriter; error NotNode(); error NotBackend(); /// Callable only by NodeDriverAuth (which mediates calls from SFC and from admins) modifier onlyBackend() { if (msg.sender != address(backend)) { revert NotBackend(); } _; } event UpdateValidatorWeight(uint256 indexed validatorID, uint256 weight); event UpdateValidatorPubkey(uint256 indexed validatorID, bytes pubkey); event UpdateNetworkRules(bytes diff); event UpdateNetworkVersion(uint256 version); event AdvanceEpochs(uint256 num); /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// Initialization is called only once, after the contract deployment. /// Because the contract code is written directly into genesis, constructor cannot be used. function initialize(address _backend, address _evmWriterAddress, address _owner) external initializer { __Ownable_init(_owner); __UUPSUpgradeable_init(); backend = NodeDriverAuth(_backend); evmWriter = IEVMWriter(_evmWriterAddress); } /// Override the upgrade authorization check to allow upgrades only from the owner. // solhint-disable-next-line no-empty-blocks function _authorizeUpgrade(address) internal override onlyOwner {} function setBalance(address acc, uint256 value) external onlyBackend { evmWriter.setBalance(acc, value); } function copyCode(address acc, address from) external onlyBackend { evmWriter.copyCode(acc, from); } function swapCode(address acc, address where) external onlyBackend { evmWriter.swapCode(acc, where); } function setStorage(address acc, bytes32 key, bytes32 value) external onlyBackend { evmWriter.setStorage(acc, key, value); } function incNonce(address acc, uint256 diff) external onlyBackend { evmWriter.incNonce(acc, diff); } /// Update network rules configuring the chain. /// Emitted event is being observed by Sonic client. function updateNetworkRules(bytes calldata diff) external onlyBackend { emit UpdateNetworkRules(diff); } /// Update advertised version of the network. /// Emitted event is being observed by Sonic client. function updateNetworkVersion(uint256 version) external onlyBackend { emit UpdateNetworkVersion(version); } /// Enforce sealing given number of epochs. /// Emitted event is being observed by Sonic client. function advanceEpochs(uint256 num) external onlyBackend { emit AdvanceEpochs(num); } /// Update weight of a validator. Used to propagate a stake change from SFC to the client. /// Emitted event is being observed by Sonic client. function updateValidatorWeight(uint256 validatorID, uint256 value) external onlyBackend { emit UpdateValidatorWeight(validatorID, value); } /// Update public key of a validator. Used to propagate a change from SFC to the client. /// Emitted event is being observed by Sonic client. function updateValidatorPubkey(uint256 validatorID, bytes calldata pubkey) external onlyBackend { emit UpdateValidatorPubkey(validatorID, pubkey); } /// Callable only from Sonic client itself as an internal tx. /// Used for propagating network event (validator doublesign, epoch sealing) from node to SFC. modifier onlyNode() { if (msg.sender != address(0)) { revert NotNode(); } _; } // Methods which are called only by the node /// Set an initial validator. Called only as part of network initialization/genesis file generating. function setGenesisValidator( address auth, uint256 validatorID, bytes calldata pubkey, uint256 createdTime ) external onlyNode { backend.setGenesisValidator(auth, validatorID, pubkey, createdTime); } /// Set an initial delegation. Called only as part of network initialization/genesis file generating. function setGenesisDelegation(address delegator, uint256 toValidatorID, uint256 stake) external onlyNode { backend.setGenesisDelegation(delegator, toValidatorID, stake); } /// Deactivate a validator. Called by network node when a double-sign of the given validator is registered. /// Is called before sealEpoch() call. function deactivateValidator(uint256 validatorID, uint256 status) external onlyNode { backend.deactivateValidator(validatorID, status); } /// Seal epoch. Called BEFORE epoch sealing made by the client itself. function sealEpoch( uint256[] calldata offlineTimes, uint256[] calldata offlineBlocks, uint256[] calldata uptimes, uint256[] calldata originatedTxsFee ) external onlyNode { backend.sealEpoch(offlineTimes, offlineBlocks, uptimes, originatedTxsFee); } /// Seal epoch. Called AFTER epoch sealing made by the client itself. function sealEpochValidators(uint256[] calldata nextValidatorIDs) external onlyNode { backend.sealEpochValidators(nextValidatorIDs); } uint256[50] private __gap; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {ISFC} from "../interfaces/ISFC.sol"; import {NodeDriver} from "./NodeDriver.sol"; import {INodeDriverExecutable} from "../interfaces/INodeDriverExecutable.sol"; /** * @custom:security-contact [email protected] */ contract NodeDriverAuth is OwnableUpgradeable, UUPSUpgradeable { ISFC internal sfc; NodeDriver internal driver; error NotSFC(); error NotDriver(); error NotContract(); error SelfCodeHashMismatch(); error DriverCodeHashMismatch(); error RecipientNotSFC(); /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } // Initialize NodeDriverAuth, NodeDriver and SFC in one call to allow fewer genesis transactions function initialize(address payable _sfc, address _driver, address _owner) external initializer { __Ownable_init(_owner); __UUPSUpgradeable_init(); driver = NodeDriver(_driver); sfc = ISFC(_sfc); } /// Override the upgrade authorization check to allow upgrades only from the owner. // solhint-disable-next-line no-empty-blocks function _authorizeUpgrade(address) internal override onlyOwner {} /// Callable only by SFC contract. modifier onlySFC() { if (msg.sender != address(sfc)) { revert NotSFC(); } _; } /// Callable only by NodeDriver (mediates messages from the network client) modifier onlyDriver() { if (msg.sender != address(driver)) { revert NotDriver(); } _; } function _execute(address executable, address newOwner, bytes32 selfCodeHash, bytes32 driverCodeHash) internal { _transferOwnership(executable); INodeDriverExecutable(executable).execute(); _transferOwnership(newOwner); //require(driver.backend() == address(this), "ownership of driver is lost"); if (_getCodeHash(address(this)) != selfCodeHash) { revert SelfCodeHashMismatch(); } if (_getCodeHash(address(driver)) != driverCodeHash) { revert DriverCodeHashMismatch(); } } /// Execute a batch update of network configuration. /// Run given contract with a permission of the NodeDriverAuth owner. /// Does not allow changing NodeDriver and NodeDriverAuth code. function execute(address executable) external onlyOwner { _execute(executable, owner(), _getCodeHash(address(this)), _getCodeHash(address(driver))); } /// Execute a batch update of network configuration. /// Run given contract with a permission of the NodeDriverAuth owner. /// Allows changing NodeDriver and NodeDriverAuth code. function mutExecute( address executable, address newOwner, bytes32 selfCodeHash, bytes32 driverCodeHash ) external onlyOwner { _execute(executable, newOwner, selfCodeHash, driverCodeHash); } /// Mint native token. To be used by SFC for minting validators rewards. function incBalance(address acc, uint256 diff) external onlySFC { driver.setBalance(acc, address(acc).balance + diff); } /// Upgrade code of given contract by coping it from other deployed contract. /// Avoids setting code to an external address. function upgradeCode(address acc, address from) external onlyOwner { if (!isContract(acc) || !isContract(from)) { revert NotContract(); } driver.copyCode(acc, from); } /// Upgrade code of given contract by coping it from other deployed contract. /// Does not avoid setting code to an external address. (DANGEROUS!) function copyCode(address acc, address from) external onlyOwner { driver.copyCode(acc, from); } /// Increment nonce of the given account. function incNonce(address acc, uint256 diff) external onlyOwner { driver.incNonce(acc, diff); } /// Update network rules by providing a JSON patch. function updateNetworkRules(bytes calldata diff) external onlyOwner { driver.updateNetworkRules(diff); } /// Update advertised network version. function updateNetworkVersion(uint256 version) external onlyOwner { driver.updateNetworkVersion(version); } /// Enforce sealing given number of epochs. function advanceEpochs(uint256 num) external onlyOwner { driver.advanceEpochs(num); } /// Update weight of a validator. Used to propagate a stake change from SFC to the client. function updateValidatorWeight(uint256 validatorID, uint256 value) external onlySFC { driver.updateValidatorWeight(validatorID, value); } /// Update public key of a validator. Used to propagate a change from SFC to the client. function updateValidatorPubkey(uint256 validatorID, bytes calldata pubkey) external onlySFC { driver.updateValidatorPubkey(validatorID, pubkey); } /// Set an initial validator into SFC. Called only as part of network initialization/genesis file generating. function setGenesisValidator( address auth, uint256 validatorID, bytes calldata pubkey, uint256 createdTime ) external onlyDriver { sfc.setGenesisValidator(auth, validatorID, pubkey, createdTime); } /// Set an initial delegation. Called only as part of network initialization/genesis file generating. function setGenesisDelegation(address delegator, uint256 toValidatorID, uint256 stake) external onlyDriver { sfc.setGenesisDelegation(delegator, toValidatorID, stake); } /// Deactivate a validator. Called by network node when a double-sign of the given validator is registered. /// Is called before sealEpoch() call. function deactivateValidator(uint256 validatorID, uint256 status) external onlyDriver { sfc.deactivateValidator(validatorID, status); } /// Seal epoch. Called BEFORE epoch sealing made by the client itself. function sealEpoch( uint256[] calldata offlineTimes, uint256[] calldata offlineBlocks, uint256[] calldata uptimes, uint256[] calldata originatedTxsFee ) external onlyDriver { sfc.sealEpoch(offlineTimes, offlineBlocks, uptimes, originatedTxsFee); } /// Seal epoch. Called AFTER epoch sealing made by the client itself. function sealEpochValidators(uint256[] calldata nextValidatorIDs) external onlyDriver { sfc.sealEpochValidators(nextValidatorIDs); } function isContract(address account) internal view returns (bool) { uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } function _getCodeHash(address addr) internal view returns (bytes32) { bytes32 codeHash; assembly { codeHash := extcodehash(addr) } return codeHash; } uint256[50] private __gap; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; contract FailingReceiver { // Fallback function to reject any received Ether receive() external payable { revert("Forced transfer failure"); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; import {ConstantsManager} from "../sfc/ConstantsManager.sol"; contract UnitTestConstantsManager is ConstantsManager { constructor(address owner) ConstantsManager(owner) {} function updateMinSelfStake(uint256 v) external override onlyOwner { minSelfStake = v; } function updateBaseRewardPerSecond(uint256 v) external override onlyOwner { baseRewardPerSecond = v; } function updateGasPriceBalancingCounterweight(uint256 v) external override onlyOwner { gasPriceBalancingCounterweight = v; } function updateOfflinePenaltyThresholdTime(uint256 v) external override onlyOwner { offlinePenaltyThresholdTime = v; } function updateTargetGasPowerPerSecond(uint256 v) external override onlyOwner { targetGasPowerPerSecond = v; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; import {Decimal} from "../common/Decimal.sol"; import {SFC} from "../sfc/SFC.sol"; import {ISFC} from "../interfaces/ISFC.sol"; import {NodeDriverAuth} from "../sfc/NodeDriverAuth.sol"; import {NodeDriver} from "../sfc/NodeDriver.sol"; import {UnitTestConstantsManager} from "./UnitTestConstantsManager.sol"; contract UnitTestSFC is SFC { uint256 internal time; bool public allowedNonNodeCalls; function rebaseTime() external { time = block.timestamp; } function advanceTime(uint256 diff) external { time += diff; } function getTime() external view returns (uint256) { return time; } function getBlockTime() external view returns (uint256) { return block.timestamp; } function enableNonNodeCalls() external { allowedNonNodeCalls = true; } function disableNonNodeCalls() external { allowedNonNodeCalls = false; } function _now() internal view override returns (uint256) { return time; } function isNode(address addr) internal view override returns (bool) { if (allowedNonNodeCalls) { return true; } return SFC.isNode(addr); } } contract UnitTestNetworkInitializer { function initializeAll( uint256 sealedEpoch, uint256 totalSupply, address payable _sfc, address _auth, address _driver, address _evmWriter, address _owner ) external { NodeDriver(_driver).initialize(_auth, _evmWriter, _owner); NodeDriverAuth(_auth).initialize(_sfc, _driver, _owner); UnitTestConstantsManager consts = new UnitTestConstantsManager(address(this)); consts.updateMinSelfStake(0.3175000 * 1e18); consts.updateMaxDelegatedRatio(16 * Decimal.unit()); consts.updateValidatorCommission((15 * Decimal.unit()) / 100); consts.updateBurntFeeShare((20 * Decimal.unit()) / 100); consts.updateTreasuryFeeShare((10 * Decimal.unit()) / 100); consts.updateWithdrawalPeriodEpochs(3); consts.updateWithdrawalPeriodTime(60 * 60 * 24 * 7); consts.updateBaseRewardPerSecond(6183414351851851852); consts.updateOfflinePenaltyThresholdTime(3 days); consts.updateOfflinePenaltyThresholdBlocksNum(1000); consts.updateTargetGasPowerPerSecond(2000000); consts.updateGasPriceBalancingCounterweight(6 * 60 * 60); consts.updateAverageUptimeEpochWindow(10); consts.updateMinAverageUptime(0); // check disabled by default consts.transferOwnership(_owner); ISFC(_sfc).initialize(sealedEpoch, totalSupply, _auth, address(consts), _owner); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.27; /** * @dev Version contract gives the versioning information of the implementation contract */ contract Version { /** * @dev Returns the version of the SFC contract */ function version() public pure returns (bytes3) { return 0x040000; // version 4.0.0 } }
{ "evmVersion": "cancun", "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[],"name":"AlreadyRedirected","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"InsufficientSelfStake","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"MalformedPubkey","type":"error"},{"inputs":[],"name":"NoUnresolvedTreasuryFees","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotDeactivatedStatus","type":"error"},{"inputs":[],"name":"NotDriverAuth","type":"error"},{"inputs":[],"name":"NotEnoughEpochsPassed","type":"error"},{"inputs":[],"name":"NotEnoughTimePassed","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"NothingToStash","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"PubkeyUsedByOtherValidator","type":"error"},{"inputs":[],"name":"Redirected","type":"error"},{"inputs":[],"name":"RefundRatioTooHigh","type":"error"},{"inputs":[],"name":"RequestExists","type":"error"},{"inputs":[],"name":"RequestNotExists","type":"error"},{"inputs":[],"name":"SameAddress","type":"error"},{"inputs":[],"name":"SameRedirectionAuthorizer","type":"error"},{"inputs":[],"name":"StakeIsFullySlashed","type":"error"},{"inputs":[],"name":"StakeSubscriberFailed","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"TransfersNotAllowed","type":"error"},{"inputs":[],"name":"TreasuryNotSet","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"inputs":[],"name":"ValidatorDelegationLimitExceeded","type":"error"},{"inputs":[],"name":"ValidatorExists","type":"error"},{"inputs":[],"name":"ValidatorNotActive","type":"error"},{"inputs":[],"name":"ValidatorNotExists","type":"error"},{"inputs":[],"name":"ValidatorNotSlashed","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"inputs":[],"name":"ZeroRewards","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"AnnouncedRedirection","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BurntFTM","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"validatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"status","type":"uint256"}],"name":"ChangedValidatorStatus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewards","type":"uint256"}],"name":"ClaimedRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"validatorID","type":"uint256"},{"indexed":true,"internalType":"address","name":"auth","type":"address"},{"indexed":false,"internalType":"uint256","name":"createdEpoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"createdTime","type":"uint256"}],"name":"CreatedValidator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"validatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deactivatedEpoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deactivatedTime","type":"uint256"}],"name":"DeactivatedValidator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Delegated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","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":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"validatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RefundedSlashedLegacyDelegation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewards","type":"uint256"}],"name":"RestakedRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TreasuryFeesResolved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"wrID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Undelegated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"validatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"refundRatio","type":"uint256"}],"name":"UpdatedSlashingRefundRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"wrID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"penalty","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"},{"internalType":"bool","name":"syncPubkey","type":"bool"}],"name":"_syncValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"announceRedirection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFTM","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"constsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"pubkey","type":"bytes"}],"name":"createValidator","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"currentEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentSealedEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"},{"internalType":"uint256","name":"status","type":"uint256"}],"name":"deactivateValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"delegate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"getEpochAccumulatedOriginatedTxsFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"getEpochAccumulatedRewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"getEpochAccumulatedUptime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"getEpochAverageUptime","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"getEpochEndBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"getEpochOfflineBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"getEpochOfflineTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"getEpochReceivedStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"getEpochSnapshot","outputs":[{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"uint256","name":"epochFee","type":"uint256"},{"internalType":"uint256","name":"baseRewardPerSecond","type":"uint256"},{"internalType":"uint256","name":"totalStake","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"getEpochValidatorIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"}],"name":"getRedirection","outputs":[{"internalType":"address","name":"receiver","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"}],"name":"getRedirectionRequest","outputs":[{"internalType":"address","name":"receiver","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"getSelfStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"getStake","outputs":[{"internalType":"uint256","name":"stake","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"getValidator","outputs":[{"internalType":"uint256","name":"status","type":"uint256"},{"internalType":"uint256","name":"receivedStake","type":"uint256"},{"internalType":"address","name":"auth","type":"address"},{"internalType":"uint256","name":"createdEpoch","type":"uint256"},{"internalType":"uint256","name":"createdTime","type":"uint256"},{"internalType":"uint256","name":"deactivatedTime","type":"uint256"},{"internalType":"uint256","name":"deactivatedEpoch","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"auth","type":"address"}],"name":"getValidatorID","outputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"getValidatorPubkey","outputs":[{"internalType":"bytes","name":"pubkey","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"validatorID","type":"uint256"},{"internalType":"uint256","name":"wrID","type":"uint256"}],"name":"getWithdrawalRequest","outputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"sealedEpoch","type":"uint256"},{"internalType":"uint256","name":"_totalSupply","type":"uint256"},{"internalType":"address","name":"nodeDriver","type":"address"},{"internalType":"address","name":"_c","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"initiateRedirection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"isSlashed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"issueTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastValidatorID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"pendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pubkeyAddress","type":"address"}],"name":"pubkeyAddressToValidatorID","outputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"redirect","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redirectionAuthorizer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resolveTreasuryFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"restakeRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"rewardsStash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"offlineTime","type":"uint256[]"},{"internalType":"uint256[]","name":"offlineBlocks","type":"uint256[]"},{"internalType":"uint256[]","name":"uptimes","type":"uint256[]"},{"internalType":"uint256[]","name":"originatedTxsFee","type":"uint256[]"}],"name":"sealEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nextValidatorIDs","type":"uint256[]"}],"name":"sealEpochValidators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"internalType":"uint256","name":"stake","type":"uint256"}],"name":"setGenesisDelegation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"auth","type":"address"},{"internalType":"uint256","name":"validatorID","type":"uint256"},{"internalType":"bytes","name":"pubkey","type":"bytes"},{"internalType":"uint256","name":"createdTime","type":"uint256"}],"name":"setGenesisValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"v","type":"address"}],"name":"setRedirectionAuthorizer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"slashingRefundRatio","outputs":[{"internalType":"uint256","name":"refundRatio","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakeSubscriberAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"stashRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"stashedRewardsUntilEpoch","outputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalActiveStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","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":[],"name":"treasuryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"internalType":"uint256","name":"wrID","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"undelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unresolvedTreasuryFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"v","type":"address"}],"name":"updateConstsAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"},{"internalType":"uint256","name":"refundRatio","type":"uint256"}],"name":"updateSlashingRefundRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"v","type":"address"}],"name":"updateStakeSubscriberAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"v","type":"address"}],"name":"updateTreasuryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"bytes3","name":"","type":"bytes3"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"internalType":"uint256","name":"wrID","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6080604052600436106103d7575f3560e01c80638cddb015116101ff578063c65ee0e111610113578063dc31e1af116100a8578063e880a15911610078578063e880a15914610e10578063e9a505a714610e2f578063ebdf104c14610e4e578063f2fde38b14610e6d578063fb36025f14610e8c575f5ffd5b8063dc31e1af14610d43578063df00c92214610d7d578063e08d7e6614610db7578063e261641a14610dd6575f5ffd5b8063cfd47663116100e3578063cfd4766314610ca3578063d46fa51814610cd9578063d725e91f14610cf6578063db5ca3e514610d15575f5ffd5b8063c65ee0e114610c25578063c7be95de14610c50578063cc17278414610c65578063cc8343aa14610c84575f5ffd5b8063a86a056f11610194578063b0ef386c11610164578063b0ef386c14610ad8578063b5d8962714610af7578063b88a37e214610b9a578063c3de580e14610bc6578063c5f956af14610c06575f5ffd5b8063a86a056f146109f8578063a8ab09ba14610a2e578063aa5d829214610a4d578063ad3cb1cc14610aa8575f5ffd5b80639fa6dd35116101cf5780639fa6dd3514610979578063a198d2291461098c578063a5820daa146109c6578063a5a470ad146109e5575f5ffd5b80638cddb015146108ea5780638d2da32e146109095780638da5cb5b1461091e57806390a6c4751461095a575f5ffd5b806352d1902d116102f6578063736de9ae1161028b578063841e45611161025b578063841e45611461085757806384b863e014610876578063854873e11461088a578063860c2750146108b65780638b0e9f3f146108d5575f5ffd5b8063736de9ae146107db578063766718081461080f57806376fed43a146108235780637cacb1d614610842575f5ffd5b80636099ecb2116102c65780636099ecb21461072d57806361e53fcc1461074c5780636f49866314610786578063715018a6146107c7575f5ffd5b806352d1902d146106bd57806354fd4d50146106d15780635601fe01146106ef57806358f95b801461070e575f5ffd5b806339b80c001161036c57806346f1ca351161033c57806346f1ca351461064d5780634f1ef2861461066c5780634f7c4efb1461067f5780634f864df41461069e575f5ffd5b806339b80c001461055d5780633fbfd4df146105db578063441a3e70146105fa578063468f35ee14610619575f5ffd5b806318160ddd116103a757806318160ddd146104ae5780631e702f83146104c35780631f270152146104e257806328f7314814610548575f5ffd5b80630135b1db146103f957806308c3687414610437578063093b41d0146104585780630962ef791461048f575f5ffd5b366103f55760405163ab064ad360e01b815260040160405180910390fd5b5f5ffd5b348015610404575f5ffd5b506104246104133660046145a6565b60036020525f908152604090205481565b6040519081526020015b60405180910390f35b348015610442575f5ffd5b506104566104513660046145c1565b610eb7565b005b348015610463575f5ffd5b50601254610477906001600160a01b031681565b6040516001600160a01b03909116815260200161042e565b34801561049a575f5ffd5b506104566104a93660046145c1565b610f19565b3480156104b9575f5ffd5b50610424600d5481565b3480156104ce575f5ffd5b506104566104dd3660046145d8565b610fe9565b3480156104ed575f5ffd5b5061052d6104fc3660046145f8565b600b60209081525f938452604080852082529284528284209052825290208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161042e565b348015610553575f5ffd5b5061042460075481565b348015610568575f5ffd5b506105ae6105773660046145c1565b600e6020525f9081526040902060088101546009820154600a830154600b840154600c850154600d90950154939492939192909186565b604080519687526020870195909552938501929092526060840152608083015260a082015260c00161042e565b3480156105e6575f5ffd5b506104566105f536600461462a565b611072565b348015610605575f5ffd5b506104566106143660046145d8565b6111db565b348015610624575f5ffd5b506104776106333660046145a6565b60156020525f90815260409020546001600160a01b031681565b348015610658575f5ffd5b506104566106673660046145a6565b6111f3565b61045661067a366004614699565b61122b565b34801561068a575f5ffd5b506104566106993660046145d8565b611246565b3480156106a9575f5ffd5b506104566106b836600461475c565b6112f5565b3480156106c8575f5ffd5b50610424611442565b3480156106dc575f5ffd5b50604051600160fa1b815260200161042e565b3480156106fa575f5ffd5b506104246107093660046145c1565b61145d565b348015610719575f5ffd5b506104246107283660046145d8565b61148f565b348015610738575f5ffd5b50610424610747366004614785565b6114af565b348015610757575f5ffd5b506104246107663660046145d8565b5f918252600e602090815260408084209284526001909201905290205490565b348015610791575f5ffd5b506104246107a0366004614785565b6001600160a01b03919091165f908152600960209081526040808320938352929052205490565b3480156107d2575f5ffd5b506104566114f4565b3480156107e6575f5ffd5b506104776107f53660046145a6565b60166020525f90815260409020546001600160a01b031681565b34801561081a575f5ffd5b50610424611507565b34801561082e575f5ffd5b5061045661083d3660046147f3565b61151c565b34801561084d575f5ffd5b5061042460015481565b348015610862575f5ffd5b506104566108713660046145a6565b61156e565b348015610881575f5ffd5b50610456611598565b348015610895575f5ffd5b506108a96108a43660046145c1565b61169d565b60405161042e919061487f565b3480156108c1575f5ffd5b506104566108d03660046145a6565b611734565b3480156108e0575f5ffd5b5061042460065481565b3480156108f5575f5ffd5b50610456610904366004614785565b61175e565b348015610914575f5ffd5b5061042460085481565b348015610929575f5ffd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316610477565b348015610965575f5ffd5b506104566109743660046145c1565b611785565b6104566109873660046145c1565b611799565b348015610997575f5ffd5b506104246109a63660046145d8565b5f918252600e602090815260408084209284526006909201905290205490565b3480156109d1575f5ffd5b506104566109e03660046145c1565b6117a4565b6104566109f3366004614891565b611927565b348015610a03575f5ffd5b50610424610a12366004614785565b600a60209081525f928352604080842090915290825290205481565b348015610a39575f5ffd5b50610456610a483660046145f8565b611a6e565b348015610a58575f5ffd5b50610a90610a673660046145d8565b5f918252600e60209081526040808420928452600390920190529020546001600160401b031690565b6040516001600160401b03909116815260200161042e565b348015610ab3575f5ffd5b506108a9604051806040016040528060058152602001640352e302e360dc1b81525081565b348015610ae3575f5ffd5b50610456610af23660046145a6565b611aad565b348015610b02575f5ffd5b50610b57610b113660046145c1565b600260208190525f918252604090912080546001820154928201546003830154600484015460058501546006909501549395946001600160a01b03909316939192909187565b6040805197885260208801969096526001600160a01b03909416948601949094526060850191909152608084015260a083019190915260c082015260e00161042e565b348015610ba5575f5ffd5b50610bb9610bb43660046145c1565b611b05565b60405161042e91906148cf565b348015610bd1575f5ffd5b50610bf6610be03660046145c1565b5f90815260026020526040902054608016151590565b604051901515815260200161042e565b348015610c11575f5ffd5b50601054610477906001600160a01b031681565b348015610c30575f5ffd5b50610424610c3f3660046145c1565b600f6020525f908152604090205481565b348015610c5b575f5ffd5b5061042460055481565b348015610c70575f5ffd5b50610456610c7f366004614911565b611b67565b348015610c8f575f5ffd5b50610456610c9e366004614948565b611c2d565b348015610cae575f5ffd5b50610424610cbd366004614785565b600c60209081525f928352604080842090915290825290205481565b348015610ce4575f5ffd5b506011546001600160a01b0316610477565b348015610d01575f5ffd5b50610456610d103660046145a6565b611d57565b348015610d20575f5ffd5b50610424610d2f3660046145c1565b5f908152600e602052604090206009015490565b348015610d4e575f5ffd5b50610424610d5d3660046145d8565b5f918252600e602090815260408084209284526004909201905290205490565b348015610d88575f5ffd5b50610424610d973660046145d8565b5f918252600e602090815260408084209284526002909201905290205490565b348015610dc2575f5ffd5b50610456610dd13660046149af565b611dfd565b348015610de1575f5ffd5b50610424610df03660046145d8565b5f918252600e602090815260408084209284526005909201905290205490565b348015610e1b575f5ffd5b50610456610e2a3660046145a6565b611ebe565b348015610e3a575f5ffd5b50601454610477906001600160a01b031681565b348015610e59575f5ffd5b50610456610e683660046149e1565b611ee8565b348015610e78575f5ffd5b50610456610e873660046145a6565b61218c565b348015610e97575f5ffd5b50610424610ea63660046145a6565b60136020525f908152604090205481565b335f610ec382846121cb565b9050610ed082848361224e565b82826001600160a01b03167f663e0f63f4fc6b01be195c4b56111fd6f14b947d6264497119b08daf77e26da583604051610f0c91815260200190565b60405180910390a3505050565b335f610f2582846121cb565b90505f610f31836122db565b6001600160a01b0316826040515f6040518083038185875af1925050503d805f8114610f78576040519150601f19603f3d011682016040523d82523d5f602084013e610f7d565b606091505b5050905080610f9f576040516312171d8360e31b815260040160405180910390fd5b83836001600160a01b03167f70de20a533702af05c8faf1637846c4586a021bbc71b6928b089b6d555e4fbc284604051610fdb91815260200190565b60405180910390a350505050565b5f546001600160a01b031633146110135760405163c78d372960e01b815260040160405180910390fd5b806110315760405163396bd83560e21b815260040160405180910390fd5b61103b8282612303565b611045825f611c2d565b5f828152600260208190526040822001546001600160a01b03169061106d9082908190612405565b505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f811580156110b65750825b90505f826001600160401b031660011480156110d15750303b155b9050811580156110df575080155b156110fd5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561112757845460ff60401b1916600160401b1785555b611130866124e1565b6111386124f2565b60018a90555f80546001600160a01b03808b166001600160a01b03199283161790925560118054928a1692909116919091179055600d8990556111784290565b5f8b8152600e602052604090206008015583156111cf57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050505050565b6111ef3383836111ea336122db565b6124fa565b5050565b6040516001600160a01b0382169033907f857125196131cfcd709c738c6d1fd2701ce70f2a03785aeadae6f4b47fe73c1d905f90a350565b611233612894565b61123c82612938565b6111ef8282612940565b61124e6129fc565b5f8281526002602052604090205460801661127c576040516321b6a8f960e11b815260040160405180910390fd5b670de0b6b3a76400008111156112a5576040516357c70d6360e01b815260040160405180910390fd5b5f828152600f6020526040908190208290555182907f047575f43f09a7a093d94ec483064acfc61b7e25c0de28017da442abf99cb917906112e99084815260200190565b60405180910390a25050565b336113008185612a57565b50815f0361132157604051631f2a200560e01b815260040160405180910390fd5b6001600160a01b0381165f908152600b6020908152604080832087845282528083208684529091529020600201541561136d5760405163756f5c2d60e11b815260040160405180910390fd5b61137d81858460015f6001612ac5565b6001600160a01b0381165f908152600b60209081526040808320878452825280832086845290915290206002018290556113b5611507565b6001600160a01b0382165f908152600b6020908152604080832088845282528083208784529091528120918255426001909201919091556113f7908590611c2d565b8284826001600160a01b03167fd3bb4e423fbea695d16b982f9f682dc5f35152e5411646a8a5a79a6b02ba8d578560405161143491815260200190565b60405180910390a450505050565b5f61144b612c96565b505f516020614eb75f395f51905f5290565b5f818152600260208181526040808420909201546001600160a01b03168352600c815281832093835292909252205490565b5f828152600e602090815260408083208484529091529020545b92915050565b5f5f6114bb8484612cdf565b6001600160a01b0385165f9081526009602090815260408083208784529091529020549091506114ec908290614abf565b949350505050565b6114fc6129fc565b6115055f612d49565b565b5f60015460016115179190614abf565b905090565b5f546001600160a01b031633146115465760405163c78d372960e01b815260040160405180910390fd5b611557858585855f5f875f5f612db9565b6005548411156115675760058490555b5050505050565b6115766129fc565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b6010546001600160a01b03166115c15760405163b2c4cce960e01b815260040160405180910390fd5b6008545f036115e35760405163211a852360e21b815260040160405180910390fd5b600880545f918290556010546040519192916001600160a01b0390911690620f424090849084818181858888f193505050503d805f811461163f576040519150601f19603f3d011682016040523d82523d5f602084013e611644565b606091505b5050905080611666576040516312171d8360e31b815260040160405180910390fd5b6040518281527f6dd5bb8ebf4cfb647c1cc0e9364ed9ecbf56202f7d3c9f058473df82664478d89060200160405180910390a15050565b60046020525f9081526040902080546116b590614ad2565b80601f01602080910402602001604051908101604052809291908181526020018280546116e190614ad2565b801561172c5780601f106117035761010080835404028352916020019161172c565b820191905f5260205f20905b81548152906001019060200180831161170f57829003601f168201915b505050505081565b61173c6129fc565b601180546001600160a01b0319166001600160a01b0392909216919091179055565b6117688282612a57565b6111ef5760405163208e0a4160e11b815260040160405180910390fd5b61178d6129fc565b61179681612f64565b50565b61179633823461224e565b6117ac6129fc565b601154604080516375840fab60e01b815290515f926001600160a01b0316916375840fab9160048083019260209291908290030181865afa1580156117f3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118179190614b0a565b6001600160a01b03160361183e5760405163d92e233d60e01b815260040160405180910390fd5b5f54601154604080516375840fab60e01b815290516001600160a01b03938416936366e7ea0f9316916375840fab9160048083019260209291908290030181865afa15801561188f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118b39190614b0a565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044015f604051808303815f87803b1580156118f8575f5ffd5b505af115801561190a573d5f5f3e3d5ffd5b5050505080600d5f82825461191f9190614abf565b909155505050565b60115f9054906101000a90046001600160a01b03166001600160a01b031663c5f530af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611977573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061199b9190614b25565b3410156119bb5760405163047447a360e11b815260040160405180910390fd5b6042811415806119f4575081815f8181106119d8576119d8614b3c565b9050013560f81c60f81b6001600160f81b03191660c060f81b14155b15611a12576040516338497f4960e11b815260040160405180910390fd5b60135f611a1f8484612fcb565b6001600160a01b0316815260208101919091526040015f205415611a565760405163028aeb6760e21b815260040160405180910390fd5b611a61338383612ff7565b6111ef336005543461224e565b5f546001600160a01b03163314611a985760405163c78d372960e01b815260040160405180910390fd5b611aa48383835f613025565b61106d81613173565b611ab56129fc565b6014546001600160a01b03808316911603611ae357604051639b92bed360e01b815260040160405180910390fd5b601480546001600160a01b0319166001600160a01b0392909216919091179055565b5f818152600e6020908152604091829020600701805483518184028101840190945280845260609392830182828015611b5b57602002820191905f5260205f20905b815481526020019060010190808311611b47575b50505050509050919050565b6014546001600160a01b03163314611b925760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b038281165f90815260166020526040902054818316911603611bce5760405163eb81e1a360e01b815260040160405180910390fd5b806001600160a01b0316826001600160a01b031603611c005760405163367558c360e01b815260040160405180910390fd5b6001600160a01b039182165f90815260156020526040902080546001600160a01b03191691909216179055565b5f82815260026020526040902060040154611c5b57604051635926e0c360e01b815260040160405180910390fd5b5f8281526002602052604090206001810154905415611c7757505f5b5f5460405163520337df60e11b815260048101859052602481018390526001600160a01b039091169063a4066fbe906044015f604051808303815f87803b158015611cc0575f5ffd5b505af1158015611cd2573d5f5f3e3d5ffd5b50505050818015611ce257508015155b1561106d575f805484825260046020819052604092839020925163242a6e3f60e01b81526001600160a01b039092169263242a6e3f92611d259288929101614b50565b5f604051808303815f87803b158015611d3c575f5ffd5b505af1158015611d4e573d5f5f3e3d5ffd5b50505050505050565b336001600160a01b038216611d7f5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038181165f90815260156020526040902054811690831614611dbb57604051630fe3b3c160e31b815260040160405180910390fd5b6001600160a01b039081165f9081526016602090815260408083208054949095166001600160a01b031994851617909455601590529190912080549091169055565b5f546001600160a01b03163314611e275760405163c78d372960e01b815260040160405180910390fd5b5f600e5f611e33611507565b81526020019081526020015f2090505f5f90505b82811015611ea9575f848483818110611e6257611e62614b3c565b602090810292909201355f81815260028452604080822060010154948890529020839055600c860154909350611e9a91508290614abf565b600c8501555050600101611e47565b50611eb8600782018484614535565b50505050565b611ec66129fc565b601280546001600160a01b0319166001600160a01b0392909216919091179055565b5f546001600160a01b03163314611f125760405163c78d372960e01b815260040160405180910390fd5b5f600e5f611f1e611507565b81526020019081526020015f2090505f81600701805480602002602001604051908101604052809291908181526020018280548015611f7a57602002820191905f5260205f20905b815481526020019060010190808311611f66575b50505050509050611fff82828c8c808060200260200160405190810160405280939291908181526020018383602002808284375f81840152601f19601f820116905080830192505050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152506131e592505050565b600180545f908152600e60205260409020600881015490919042111561203157600882015461202e9042614bde565b90505b6120b1818584868c8c808060200260200160405190810160405280939291908181526020018383602002808284375f81840152601f19601f820116905080830192505050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152506133ff92505050565b6120f0818584868c8c808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250613b3992505050565b50506120fa611507565b6001554260088301554360098301556011546040805163d9a7c1f960e01b815290516001600160a01b039092169163d9a7c1f9916004808201926020929091908290030181865afa158015612151573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121759190614b25565b600b83015550600d80549101555050505050505050565b6121946129fc565b6001600160a01b0381166121c257604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61179681612d49565b5f6121d68383612a57565b506001600160a01b0383165f9081526009602090815260408083208584529091528120549081900361221b5760405163899aaa9d60e01b815260040160405180910390fd5b6001600160a01b0384165f90815260096020908152604080832086845290915281205561224781613173565b9392505050565b5f8281526002602052604090206004015461227c57604051635926e0c360e01b815260040160405180910390fd5b5f82815260026020526040902054156122a8576040516353670afb60e11b815260040160405180910390fd5b6122b58383836001613025565b6122be82613db7565b61106d5760405163c2eb4ead60e01b815260040160405180910390fd5b6001600160a01b038082165f90815260166020526040812054909116806114a9575090919050565b5f8281526002602052604090205415801561231d57508015155b15612344575f828152600260205260409020600101546007546123409190614bde565b6007555b5f828152600260205260409020548111156111ef575f8281526002602052604081208281556006015490036123d35761237b611507565b5f8381526002602090815260409182902060068101849055426005909101819055825193845290830152805184927fac4801c32a6067ff757446524ee4e7a373797278ac3c883eac5c693b4ad72e4792908290030190a25b817fcd35267e7654194727477d6c78b541a553483cff7f92a055d17868d3da6e953e826040516112e991815260200190565b6012546001600160a01b03161561106d576012546040516001600160a01b03858116602483015284811660448301525f921690627a12009060640160408051601f198184030181529181526020820180516001600160e01b0316631fbcb08360e11b179052516124759190614bf1565b5f604051808303815f8787f1925050503d805f81146124af576040519150601f19603f3d011682016040523d82523d5f602084013e6124b4565b606091505b50509050801580156124c35750815b15611eb8576040516347b4be6960e11b815260040160405180910390fd5b6124e9613e6e565b61179681613eb7565b611505613e6e565b6001600160a01b0384165f908152600b60209081526040808320868452825280832085845282528083208151606081018352815480825260018301549482019490945260029091015491810191909152910361256957604051630fe3b3c160e31b815260040160405180910390fd5b60208082015182515f8781526002909352604090922060050154909190158015906125a357505f8681526002602052604090206005015482115b156125c35750505f84815260026020526040902060058101546006909101545b60115f9054906101000a90046001600160a01b03166001600160a01b031663b82b84276040518163ffffffff1660e01b8152600401602060405180830381865afa158015612613573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126379190614b25565b6126419083614abf565b42101561266157604051635ada9a9960e01b815260040160405180910390fd5b60115f9054906101000a90046001600160a01b03166001600160a01b031663650acd666040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126b1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126d59190614b25565b6126df9082614abf565b6126e7611507565b1015612706576040516323ea994d60e01b815260040160405180910390fd5b6001600160a01b0387165f908152600b60209081526040808320898452825280832088845282528083206002908101548a855290835281842054600f9093529083205490926080909216151591906127619084908490613ebf565b6001600160a01b038b165f908152600b602090815260408083208d845282528083208c84529091528120818155600181018290556002015590508083116127bb576040516318f967fb60e01b815260040160405180910390fd5b5f6001600160a01b0388166127d08386614bde565b6040515f81818185875af1925050503d805f8114612809576040519150601f19603f3d011682016040523d82523d5f602084013e61280e565b606091505b5050905080612830576040516312171d8360e31b815260040160405180910390fd5b61283982612f64565b888a6001600160a01b038d167f94ffd6b85c71b847775c89ef6496b93cee961bdc6ff827fd117f174f06f745ae6128708689614bde565b60408051918252602082018890520160405180910390a45050505050505050505050565b306001600160a01b037f000000000000000000000000fc00face0000000000000000000000000000000116148061291a57507f000000000000000000000000fc00face000000000000000000000000000000016001600160a01b031661290e5f516020614eb75f395f51905f52546001600160a01b031690565b6001600160a01b031614155b156115055760405163703e46dd60e11b815260040160405180910390fd5b6117966129fc565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561299a575060408051601f3d908101601f1916820190925261299791810190614b25565b60015b6129c257604051634c9c8ce360e01b81526001600160a01b03831660048201526024016121b9565b5f516020614eb75f395f51905f5281146129f257604051632a87526960e21b8152600481018290526024016121b9565b61106d8383613f25565b33612a2e7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146115055760405163118cdaa760e01b81523360048201526024016121b9565b5f5f612a638484612cdf565b9050612a6e83613f7a565b6001600160a01b0385165f818152600a60209081526040808320888452825280832094909455918152600982528281208682529091529081208054839290612ab7908490614abf565b909155505015159392505050565b6001600160a01b0386165f908152600c6020908152604080832088845290915281208054869290612af7908490614bde565b90915550505f85815260026020526040902060010154612b18908590614bde565b5f86815260026020526040902060010155600654612b37908590614bde565b6006555f85815260026020526040902054612b5e5783600754612b5a9190614bde565b6007555b5f612b688661145d565b90508015801590612b8457505f86815260026020526040902054155b15612c645760115f9054906101000a90046001600160a01b03166001600160a01b031663c5f530af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bd9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bfd9190614b25565b811015612c2e578215612c235760405163047447a360e11b815260040160405180910390fd5b612c2e866001612303565b818015612c415750612c3f86613db7565b155b15612c5f5760405163c2eb4ead60e01b815260040160405180910390fd5b612c6f565b612c6f866001612303565b5f8681526002602081905260409091200154611d4e9088906001600160a01b031686612405565b306001600160a01b037f000000000000000000000000fc00face0000000000000000000000000000000116146115055760405163703e46dd60e11b815260040160405180910390fd5b6001600160a01b0382165f908152600a6020908152604080832084845290915281205481612d0c84613f7a565b6001600160a01b0386165f908152600c60209081526040808320888452909152812054919250612d3e82878686613fcf565b979650505050505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b6001600160a01b0389165f9081526003602052604090205415612def57604051633f4dc7d360e11b815260040160405180910390fd5b6001600160a01b0389165f8181526003602081815260408084208d90558c845260028083528185208b81559384018a905560048085018a90556005850188905560068501899055930180546001600160a01b0319169095179094555220612e57878983614c4b565b508760135f612e668a8a612fcb565b6001600160a01b03166001600160a01b031681526020019081526020015f2081905550886001600160a01b0316887f49bca1ed2666922f9f1690c26a569e1299c2a715fe57647d77e81adfabbf25bf8686604051612ece929190918252602082015260400190565b60405180910390a38115612f1857604080518381526020810183905289917fac4801c32a6067ff757446524ee4e7a373797278ac3c883eac5c693b4ad72e47910160405180910390a25b8415612f5957877fcd35267e7654194727477d6c78b541a553483cff7f92a055d17868d3da6e953e86604051612f5091815260200190565b60405180910390a25b505050505050505050565b8015611796576040515f9082156108fc0290839083818181858288f19350505050158015612f94573d5f5f3e3d5ffd5b506040518181527f8918bd6046d08b314e457977f29562c5d76a7030d79b1edba66e8a5da0b77ae89060200160405180910390a150565b5f612fd98260028186614d04565b604051612fe7929190614d2b565b6040519081900390209392505050565b5f60055f815461300690614d3a565b91829055509050611eb8848285855f61301d611507565b425f5f612db9565b815f0361304557604051631f2a200560e01b815260040160405180910390fd5b61304f8484612a57565b506001600160a01b0384165f908152600c6020908152604080832086845290915290205461307e908390614abf565b6001600160a01b0385165f908152600c602090815260408083208784528252808320939093556002905220600101546130b78382614abf565b5f858152600260205260409020600101556006546130d6908490614abf565b6006555f848152600260205260409020546130fd57826007546130f99190614abf565b6007555b613108848215611c2d565b83856001600160a01b03167f9a8f44850296624dadfd9c246d17e47171d35727a181bd090aa14bbbe00238bb8560405161314491815260200190565b60405180910390a35f84815260026020819052604090912001546115679086906001600160a01b031684612405565b5f546040516366e7ea0f60e01b8152306004820152602481018390526001600160a01b03909116906366e7ea0f906044015f604051808303815f87803b1580156131bb575f5ffd5b505af11580156131cd573d5f5f3e3d5ffd5b5050505080600d546131df9190614abf565b600d5550565b5f5b83518110156115675760115f9054906101000a90046001600160a01b03166001600160a01b0316635a68f01a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613240573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906132649190614b25565b82828151811061327657613276614b3c565b6020026020010151118015613316575060115f9054906101000a90046001600160a01b03166001600160a01b031662cc7f836040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132d5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906132f99190614b25565b83828151811061330b5761330b614b3c565b602002602001015110155b156133625761333f84828151811061333057613330614b3c565b60200260200101516008612303565b61336284828151811061335457613354614b3c565b60200260200101515f611c2d565b82818151811061337457613374614b3c565b6020026020010151856005015f86848151811061339357613393614b3c565b602002602001015181526020019081526020015f20819055508181815181106133be576133be614b3c565b6020026020010151856006015f8684815181106133dd576133dd614b3c565b60209081029190910181015182528101919091526040015f20556001016131e7565b5f6040518060a0016040528085516001600160401b0381111561342457613424614685565b60405190808252806020026020018201604052801561344d578160200160208202803683370190505b5081526020015f815260200185516001600160401b0381111561347257613472614685565b60405190808252806020026020018201604052801561349b578160200160208202803683370190505b5081526020015f81526020015f81525090505f5f90505b84518110156135db575f866004015f8784815181106134d3576134d3614b3c565b602002602001015181526020019081526020015f205490505f5f90508185848151811061350257613502614b3c565b60200260200101511115613538578185848151811061352357613523614b3c565b60200260200101516135359190614bde565b90505b8986848151811061354b5761354b614b3c565b60200260200101518261355e9190614d52565b6135689190614d7d565b8460400151848151811061357e5761357e614b3c565b602002602001018181525050836040015183815181106135a0576135a0614b3c565b602002602001015184606001516135b79190614abf565b606085015260808401516135cc908290614abf565b608085015250506001016134b2565b505f5b84518110156136c857878482815181106135fa576135fa614b3c565b60200260200101518986848151811061361557613615614b3c565b60200260200101518a5f015f8a878151811061363357613633614b3c565b602002602001015181526020019081526020015f20546136539190614d52565b61365d9190614d7d565b6136679190614d52565b6136719190614d7d565b825180518390811061368557613685614b3c565b602090810291909101015281518051829081106136a4576136a4614b3c565b602002602001015182602001516136bb9190614abf565b60208301526001016135de565b505f5b84518110156139cc575f6137738960115f9054906101000a90046001600160a01b03166001600160a01b031663d9a7c1f96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613729573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061374d9190614b25565b855180518690811061376157613761614b3c565b60200260200101518660200151614038565b90506137a583608001518460400151848151811061379357613793614b3c565b60200260200101518560600151614073565b6137af9082614abf565b90505f8683815181106137c4576137c4614b3c565b6020908102919091018101515f8181526002808452604080832090910154601154825163a778651560e01b815292519496506001600160a01b0391821695939461385c948994929093169263a778651592600480820193918290030181865afa158015613833573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138579190614b25565b6141c4565b6001600160a01b0383165f908152600c6020908152604080832087845290915290205490915080156138c0576001600160a01b0383165f908152600960209081526040808320878452909152812080548492906138ba908490614abf565b90915550505b5f6138cb8387614bde565b5f86815260026020526040812060010154919250811561390557816138f8670de0b6b3a764000085614d52565b6139029190614d7d565b90505b5f87815260018f016020526040902054613920908290614abf565b8f6001015f8981526020019081526020015f20819055508a898151811061394957613949614b3c565b60200260200101518f6004015f8981526020019081526020015f20819055508b898151811061397a5761397a614b3c565b60200260200101518e6002015f8981526020019081526020015f20546139a09190614abf565b8f6002015f8981526020019081526020015f2081905550505050505050505080806001019150506136cb565b506080810151600a8701819055600d541115613a025785600a0154600d5f8282546139f79190614bde565b90915550613a079050565b5f600d555b6010546001600160a01b031615611d4e575f670de0b6b3a764000060115f9054906101000a90046001600160a01b03166001600160a01b03166394c3e9146040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a72573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613a969190614b25565b8360800151613aa59190614d52565b613aaf9190614d7d565b9050613aba81613173565b6010546040515f916001600160a01b031690620f424090849084818181858888f193505050503d805f8114613b0a576040519150601f19603f3d011682016040523d82523d5f602084013e613b0f565b606091505b5050905080612f59578160085f828254613b299190614abf565b9091555050505050505050505050565b5f5b8251811015613daf575f838281518110613b5757613b57614b3c565b602002602001015190505f87613b72670de0b6b3a764000090565b858581518110613b8457613b84614b3c565b6020026020010151613b969190614d52565b613ba09190614d7d565b9050670de0b6b3a7640000811115613bbd5750670de0b6b3a76400005b5f8281526003870160209081526040808320815160608101835290546001600160401b038116825263ffffffff600160401b8204811694830194909452600160601b90049092169082015290613c1383836141e2565b5f85815260038b0160209081526040918290208351815485840151868601516001600160401b039093166bffffffffffffffffffffffff1990921691909117600160401b63ffffffff928316021763ffffffff60601b1916600160601b91909216021790556011548251631c25433760e01b815292519394506001600160a01b031692631c2543379260048082019392918290030181865afa158015613cbb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613cdf9190614d90565b6001600160401b0316815f01516001600160401b0316108015613d85575060115f9054906101000a90046001600160a01b03166001600160a01b0316633fa225486040518163ffffffff1660e01b8152600401602060405180830381865afa158015613d4d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613d719190614db6565b63ffffffff16816040015163ffffffff1610155b15613d9f57613d95846010612303565b613d9f845f611c2d565b505060019092019150613b3b9050565b505050505050565b5f670de0b6b3a764000060115f9054906101000a90046001600160a01b03166001600160a01b0316632265f2846040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e11573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e359190614b25565b613e3e8461145d565b613e489190614d52565b613e529190614d7d565b5f92835260026020526040909220600101549190911115919050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661150557604051631afcd79f60e31b815260040160405180910390fd5b612194613e6e565b5f821580613ed55750670de0b6b3a76400008210155b15613ee157505f612247565b670de0b6b3a7640000613ef48382614bde565b613efe9086614d52565b613f089190614d7d565b613f13906001614abf565b90508381111561224757509192915050565b613f2e826143c5565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115613f725761106d8282614428565b6111ef614491565b5f8181526002602052604081206006015415613fc7575f828152600260205260409020600601546001541015613fb257505060015490565b505f9081526002602052604090206006015490565b505060015490565b5f818310613fde57505f6114ec565b5f838152600e6020818152604080842088855260019081018352818520548786529383528185208986520190915290912054670de0b6b3a7640000876140248484614bde565b61402e9190614d52565b612d3e9190614d7d565b5f825f0361404757505f6114ec565b5f6140528587614d52565b90508261405f8583614d52565b6140699190614d7d565b9695505050505050565b5f825f0361408257505f612247565b5f8261408e8587614d52565b6140989190614d7d565b9050670de0b6b3a764000060115f9054906101000a90046001600160a01b03166001600160a01b03166394c3e9146040518163ffffffff1660e01b8152600401602060405180830381865afa1580156140f3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906141179190614b25565b60115f9054906101000a90046001600160a01b03166001600160a01b031663c74dd6216040518163ffffffff1660e01b8152600401602060405180830381865afa158015614167573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061418b9190614b25565b61419d90670de0b6b3a7640000614bde565b6141a79190614bde565b6141b19083614d52565b6141bb9190614d7d565b95945050505050565b5f670de0b6b3a76400006141d88385614d52565b6122479190614d7d565b604080516060810182525f8082526020820181905291810191909152604080516060810182525f8082526020820181905291810191909152826040015163ffffffff165f03614245576001600160401b03841681526001604082015290506114a9565b5f836040015160016142579190614dd9565b63ffffffff1690505f846020015163ffffffff16866001600160401b0316865f01516001600160401b031660018561428f9190614df5565b6142999190614e14565b6142a39190614e3d565b6142ad9190614e3d565b90506142b98282614e5c565b6001600160401b031683526142ce8282614e89565b63ffffffff166020840152670de0b6b3a764000083516001600160401b031611156142ff57670de0b6b3a764000083525b60115f9054906101000a90046001600160a01b03166001600160a01b0316633fa225486040518163ffffffff1660e01b8152600401602060405180830381865afa15801561434f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906143739190614db6565b63ffffffff16856040015163ffffffff1610156143aa57604085015161439a906001614dd9565b63ffffffff1660408401526143bb565b60408086015163ffffffff16908401525b5090949350505050565b806001600160a01b03163b5f036143fa57604051634c9c8ce360e01b81526001600160a01b03821660048201526024016121b9565b5f516020614eb75f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f5f846001600160a01b0316846040516144449190614bf1565b5f60405180830381855af49150503d805f811461447c576040519150601f19603f3d011682016040523d82523d5f602084013e614481565b606091505b50915091506141bb8583836144b0565b34156115055760405163b398979f60e01b815260040160405180910390fd5b6060826144c5576144c08261450c565b612247565b81511580156144dc57506001600160a01b0384163b155b1561450557604051639996b31560e01b81526001600160a01b03851660048201526024016121b9565b5080612247565b80511561451c5780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b828054828255905f5260205f2090810192821561456e579160200282015b8281111561456e578235825591602001919060010190614553565b5061457a92915061457e565b5090565b5b8082111561457a575f815560010161457f565b6001600160a01b0381168114611796575f5ffd5b5f602082840312156145b6575f5ffd5b813561224781614592565b5f602082840312156145d1575f5ffd5b5035919050565b5f5f604083850312156145e9575f5ffd5b50508035926020909101359150565b5f5f5f6060848603121561460a575f5ffd5b833561461581614592565b95602085013595506040909401359392505050565b5f5f5f5f5f60a0868803121561463e575f5ffd5b8535945060208601359350604086013561465781614592565b9250606086013561466781614592565b9150608086013561467781614592565b809150509295509295909350565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156146aa575f5ffd5b82356146b581614592565b915060208301356001600160401b038111156146cf575f5ffd5b8301601f810185136146df575f5ffd5b80356001600160401b038111156146f8576146f8614685565b604051601f8201601f19908116603f011681016001600160401b038111828210171561472657614726614685565b60405281815282820160200187101561473d575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f5f5f6060848603121561476e575f5ffd5b505081359360208301359350604090920135919050565b5f5f60408385031215614796575f5ffd5b82356147a181614592565b946020939093013593505050565b5f5f83601f8401126147bf575f5ffd5b5081356001600160401b038111156147d5575f5ffd5b6020830191508360208285010111156147ec575f5ffd5b9250929050565b5f5f5f5f5f60808688031215614807575f5ffd5b853561481281614592565b94506020860135935060408601356001600160401b03811115614833575f5ffd5b61483f888289016147af565b96999598509660600135949350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6122476020830184614851565b5f5f602083850312156148a2575f5ffd5b82356001600160401b038111156148b7575f5ffd5b6148c3858286016147af565b90969095509350505050565b602080825282518282018190525f918401906040840190835b818110156149065783518352602093840193909201916001016148e8565b509095945050505050565b5f5f60408385031215614922575f5ffd5b823561492d81614592565b9150602083013561493d81614592565b809150509250929050565b5f5f60408385031215614959575f5ffd5b823591506020830135801515811461493d575f5ffd5b5f5f83601f84011261497f575f5ffd5b5081356001600160401b03811115614995575f5ffd5b6020830191508360208260051b85010111156147ec575f5ffd5b5f5f602083850312156149c0575f5ffd5b82356001600160401b038111156149d5575f5ffd5b6148c38582860161496f565b5f5f5f5f5f5f5f5f6080898b0312156149f8575f5ffd5b88356001600160401b03811115614a0d575f5ffd5b614a198b828c0161496f565b90995097505060208901356001600160401b03811115614a37575f5ffd5b614a438b828c0161496f565b90975095505060408901356001600160401b03811115614a61575f5ffd5b614a6d8b828c0161496f565b90955093505060608901356001600160401b03811115614a8b575f5ffd5b614a978b828c0161496f565b999c989b5096995094979396929594505050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156114a9576114a9614aab565b600181811c90821680614ae657607f821691505b602082108103614b0457634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215614b1a575f5ffd5b815161224781614592565b5f60208284031215614b35575f5ffd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b828152604060208201525f5f8354614b6781614ad2565b806040860152600182165f8114614b855760018114614ba157614bd2565b60ff1983166060870152606082151560051b8701019350614bd2565b865f5260205f205f5b83811015614bc957815488820160600152600190910190602001614baa565b87016060019450505b50919695505050505050565b818103818111156114a9576114a9614aab565b5f82518060208501845e5f920191825250919050565b601f82111561106d57805f5260205f20601f840160051c81016020851015614c2c5750805b601f840160051c820191505b81811015611567575f8155600101614c38565b6001600160401b03831115614c6257614c62614685565b614c7683614c708354614ad2565b83614c07565b5f601f841160018114614ca7575f8515614c905750838201355b5f19600387901b1c1916600186901b178355611567565b5f83815260208120601f198716915b82811015614cd65786850135825560209485019460019092019101614cb6565b5086821015614cf2575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b5f5f85851115614d12575f5ffd5b83861115614d1e575f5ffd5b5050820193919092039150565b818382375f9101908152919050565b5f60018201614d4b57614d4b614aab565b5060010190565b80820281158282048414176114a9576114a9614aab565b634e487b7160e01b5f52601260045260245ffd5b5f82614d8b57614d8b614d69565b500490565b5f60208284031215614da0575f5ffd5b81516001600160401b0381168114612247575f5ffd5b5f60208284031215614dc6575f5ffd5b815163ffffffff81168114612247575f5ffd5b63ffffffff81811683821601908111156114a9576114a9614aab565b6001600160801b0382811682821603908111156114a9576114a9614aab565b6001600160801b038181168382160290811690818114614e3657614e36614aab565b5092915050565b6001600160801b0381811683821601908111156114a9576114a9614aab565b5f6001600160801b03831680614e7457614e74614d69565b806001600160801b0384160491505092915050565b5f6001600160801b03831680614ea157614ea1614d69565b806001600160801b038416069150509291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122066d19146273283f0e3b105875ee752668c5f6172f37ee249748d1d959cb7042564736f6c634300081b0033
Deployed Bytecode
0x6080604052600436106103d7575f3560e01c80638cddb015116101ff578063c65ee0e111610113578063dc31e1af116100a8578063e880a15911610078578063e880a15914610e10578063e9a505a714610e2f578063ebdf104c14610e4e578063f2fde38b14610e6d578063fb36025f14610e8c575f5ffd5b8063dc31e1af14610d43578063df00c92214610d7d578063e08d7e6614610db7578063e261641a14610dd6575f5ffd5b8063cfd47663116100e3578063cfd4766314610ca3578063d46fa51814610cd9578063d725e91f14610cf6578063db5ca3e514610d15575f5ffd5b8063c65ee0e114610c25578063c7be95de14610c50578063cc17278414610c65578063cc8343aa14610c84575f5ffd5b8063a86a056f11610194578063b0ef386c11610164578063b0ef386c14610ad8578063b5d8962714610af7578063b88a37e214610b9a578063c3de580e14610bc6578063c5f956af14610c06575f5ffd5b8063a86a056f146109f8578063a8ab09ba14610a2e578063aa5d829214610a4d578063ad3cb1cc14610aa8575f5ffd5b80639fa6dd35116101cf5780639fa6dd3514610979578063a198d2291461098c578063a5820daa146109c6578063a5a470ad146109e5575f5ffd5b80638cddb015146108ea5780638d2da32e146109095780638da5cb5b1461091e57806390a6c4751461095a575f5ffd5b806352d1902d116102f6578063736de9ae1161028b578063841e45611161025b578063841e45611461085757806384b863e014610876578063854873e11461088a578063860c2750146108b65780638b0e9f3f146108d5575f5ffd5b8063736de9ae146107db578063766718081461080f57806376fed43a146108235780637cacb1d614610842575f5ffd5b80636099ecb2116102c65780636099ecb21461072d57806361e53fcc1461074c5780636f49866314610786578063715018a6146107c7575f5ffd5b806352d1902d146106bd57806354fd4d50146106d15780635601fe01146106ef57806358f95b801461070e575f5ffd5b806339b80c001161036c57806346f1ca351161033c57806346f1ca351461064d5780634f1ef2861461066c5780634f7c4efb1461067f5780634f864df41461069e575f5ffd5b806339b80c001461055d5780633fbfd4df146105db578063441a3e70146105fa578063468f35ee14610619575f5ffd5b806318160ddd116103a757806318160ddd146104ae5780631e702f83146104c35780631f270152146104e257806328f7314814610548575f5ffd5b80630135b1db146103f957806308c3687414610437578063093b41d0146104585780630962ef791461048f575f5ffd5b366103f55760405163ab064ad360e01b815260040160405180910390fd5b5f5ffd5b348015610404575f5ffd5b506104246104133660046145a6565b60036020525f908152604090205481565b6040519081526020015b60405180910390f35b348015610442575f5ffd5b506104566104513660046145c1565b610eb7565b005b348015610463575f5ffd5b50601254610477906001600160a01b031681565b6040516001600160a01b03909116815260200161042e565b34801561049a575f5ffd5b506104566104a93660046145c1565b610f19565b3480156104b9575f5ffd5b50610424600d5481565b3480156104ce575f5ffd5b506104566104dd3660046145d8565b610fe9565b3480156104ed575f5ffd5b5061052d6104fc3660046145f8565b600b60209081525f938452604080852082529284528284209052825290208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161042e565b348015610553575f5ffd5b5061042460075481565b348015610568575f5ffd5b506105ae6105773660046145c1565b600e6020525f9081526040902060088101546009820154600a830154600b840154600c850154600d90950154939492939192909186565b604080519687526020870195909552938501929092526060840152608083015260a082015260c00161042e565b3480156105e6575f5ffd5b506104566105f536600461462a565b611072565b348015610605575f5ffd5b506104566106143660046145d8565b6111db565b348015610624575f5ffd5b506104776106333660046145a6565b60156020525f90815260409020546001600160a01b031681565b348015610658575f5ffd5b506104566106673660046145a6565b6111f3565b61045661067a366004614699565b61122b565b34801561068a575f5ffd5b506104566106993660046145d8565b611246565b3480156106a9575f5ffd5b506104566106b836600461475c565b6112f5565b3480156106c8575f5ffd5b50610424611442565b3480156106dc575f5ffd5b50604051600160fa1b815260200161042e565b3480156106fa575f5ffd5b506104246107093660046145c1565b61145d565b348015610719575f5ffd5b506104246107283660046145d8565b61148f565b348015610738575f5ffd5b50610424610747366004614785565b6114af565b348015610757575f5ffd5b506104246107663660046145d8565b5f918252600e602090815260408084209284526001909201905290205490565b348015610791575f5ffd5b506104246107a0366004614785565b6001600160a01b03919091165f908152600960209081526040808320938352929052205490565b3480156107d2575f5ffd5b506104566114f4565b3480156107e6575f5ffd5b506104776107f53660046145a6565b60166020525f90815260409020546001600160a01b031681565b34801561081a575f5ffd5b50610424611507565b34801561082e575f5ffd5b5061045661083d3660046147f3565b61151c565b34801561084d575f5ffd5b5061042460015481565b348015610862575f5ffd5b506104566108713660046145a6565b61156e565b348015610881575f5ffd5b50610456611598565b348015610895575f5ffd5b506108a96108a43660046145c1565b61169d565b60405161042e919061487f565b3480156108c1575f5ffd5b506104566108d03660046145a6565b611734565b3480156108e0575f5ffd5b5061042460065481565b3480156108f5575f5ffd5b50610456610904366004614785565b61175e565b348015610914575f5ffd5b5061042460085481565b348015610929575f5ffd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316610477565b348015610965575f5ffd5b506104566109743660046145c1565b611785565b6104566109873660046145c1565b611799565b348015610997575f5ffd5b506104246109a63660046145d8565b5f918252600e602090815260408084209284526006909201905290205490565b3480156109d1575f5ffd5b506104566109e03660046145c1565b6117a4565b6104566109f3366004614891565b611927565b348015610a03575f5ffd5b50610424610a12366004614785565b600a60209081525f928352604080842090915290825290205481565b348015610a39575f5ffd5b50610456610a483660046145f8565b611a6e565b348015610a58575f5ffd5b50610a90610a673660046145d8565b5f918252600e60209081526040808420928452600390920190529020546001600160401b031690565b6040516001600160401b03909116815260200161042e565b348015610ab3575f5ffd5b506108a9604051806040016040528060058152602001640352e302e360dc1b81525081565b348015610ae3575f5ffd5b50610456610af23660046145a6565b611aad565b348015610b02575f5ffd5b50610b57610b113660046145c1565b600260208190525f918252604090912080546001820154928201546003830154600484015460058501546006909501549395946001600160a01b03909316939192909187565b6040805197885260208801969096526001600160a01b03909416948601949094526060850191909152608084015260a083019190915260c082015260e00161042e565b348015610ba5575f5ffd5b50610bb9610bb43660046145c1565b611b05565b60405161042e91906148cf565b348015610bd1575f5ffd5b50610bf6610be03660046145c1565b5f90815260026020526040902054608016151590565b604051901515815260200161042e565b348015610c11575f5ffd5b50601054610477906001600160a01b031681565b348015610c30575f5ffd5b50610424610c3f3660046145c1565b600f6020525f908152604090205481565b348015610c5b575f5ffd5b5061042460055481565b348015610c70575f5ffd5b50610456610c7f366004614911565b611b67565b348015610c8f575f5ffd5b50610456610c9e366004614948565b611c2d565b348015610cae575f5ffd5b50610424610cbd366004614785565b600c60209081525f928352604080842090915290825290205481565b348015610ce4575f5ffd5b506011546001600160a01b0316610477565b348015610d01575f5ffd5b50610456610d103660046145a6565b611d57565b348015610d20575f5ffd5b50610424610d2f3660046145c1565b5f908152600e602052604090206009015490565b348015610d4e575f5ffd5b50610424610d5d3660046145d8565b5f918252600e602090815260408084209284526004909201905290205490565b348015610d88575f5ffd5b50610424610d973660046145d8565b5f918252600e602090815260408084209284526002909201905290205490565b348015610dc2575f5ffd5b50610456610dd13660046149af565b611dfd565b348015610de1575f5ffd5b50610424610df03660046145d8565b5f918252600e602090815260408084209284526005909201905290205490565b348015610e1b575f5ffd5b50610456610e2a3660046145a6565b611ebe565b348015610e3a575f5ffd5b50601454610477906001600160a01b031681565b348015610e59575f5ffd5b50610456610e683660046149e1565b611ee8565b348015610e78575f5ffd5b50610456610e873660046145a6565b61218c565b348015610e97575f5ffd5b50610424610ea63660046145a6565b60136020525f908152604090205481565b335f610ec382846121cb565b9050610ed082848361224e565b82826001600160a01b03167f663e0f63f4fc6b01be195c4b56111fd6f14b947d6264497119b08daf77e26da583604051610f0c91815260200190565b60405180910390a3505050565b335f610f2582846121cb565b90505f610f31836122db565b6001600160a01b0316826040515f6040518083038185875af1925050503d805f8114610f78576040519150601f19603f3d011682016040523d82523d5f602084013e610f7d565b606091505b5050905080610f9f576040516312171d8360e31b815260040160405180910390fd5b83836001600160a01b03167f70de20a533702af05c8faf1637846c4586a021bbc71b6928b089b6d555e4fbc284604051610fdb91815260200190565b60405180910390a350505050565b5f546001600160a01b031633146110135760405163c78d372960e01b815260040160405180910390fd5b806110315760405163396bd83560e21b815260040160405180910390fd5b61103b8282612303565b611045825f611c2d565b5f828152600260208190526040822001546001600160a01b03169061106d9082908190612405565b505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f811580156110b65750825b90505f826001600160401b031660011480156110d15750303b155b9050811580156110df575080155b156110fd5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561112757845460ff60401b1916600160401b1785555b611130866124e1565b6111386124f2565b60018a90555f80546001600160a01b03808b166001600160a01b03199283161790925560118054928a1692909116919091179055600d8990556111784290565b5f8b8152600e602052604090206008015583156111cf57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050505050565b6111ef3383836111ea336122db565b6124fa565b5050565b6040516001600160a01b0382169033907f857125196131cfcd709c738c6d1fd2701ce70f2a03785aeadae6f4b47fe73c1d905f90a350565b611233612894565b61123c82612938565b6111ef8282612940565b61124e6129fc565b5f8281526002602052604090205460801661127c576040516321b6a8f960e11b815260040160405180910390fd5b670de0b6b3a76400008111156112a5576040516357c70d6360e01b815260040160405180910390fd5b5f828152600f6020526040908190208290555182907f047575f43f09a7a093d94ec483064acfc61b7e25c0de28017da442abf99cb917906112e99084815260200190565b60405180910390a25050565b336113008185612a57565b50815f0361132157604051631f2a200560e01b815260040160405180910390fd5b6001600160a01b0381165f908152600b6020908152604080832087845282528083208684529091529020600201541561136d5760405163756f5c2d60e11b815260040160405180910390fd5b61137d81858460015f6001612ac5565b6001600160a01b0381165f908152600b60209081526040808320878452825280832086845290915290206002018290556113b5611507565b6001600160a01b0382165f908152600b6020908152604080832088845282528083208784529091528120918255426001909201919091556113f7908590611c2d565b8284826001600160a01b03167fd3bb4e423fbea695d16b982f9f682dc5f35152e5411646a8a5a79a6b02ba8d578560405161143491815260200190565b60405180910390a450505050565b5f61144b612c96565b505f516020614eb75f395f51905f5290565b5f818152600260208181526040808420909201546001600160a01b03168352600c815281832093835292909252205490565b5f828152600e602090815260408083208484529091529020545b92915050565b5f5f6114bb8484612cdf565b6001600160a01b0385165f9081526009602090815260408083208784529091529020549091506114ec908290614abf565b949350505050565b6114fc6129fc565b6115055f612d49565b565b5f60015460016115179190614abf565b905090565b5f546001600160a01b031633146115465760405163c78d372960e01b815260040160405180910390fd5b611557858585855f5f875f5f612db9565b6005548411156115675760058490555b5050505050565b6115766129fc565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b6010546001600160a01b03166115c15760405163b2c4cce960e01b815260040160405180910390fd5b6008545f036115e35760405163211a852360e21b815260040160405180910390fd5b600880545f918290556010546040519192916001600160a01b0390911690620f424090849084818181858888f193505050503d805f811461163f576040519150601f19603f3d011682016040523d82523d5f602084013e611644565b606091505b5050905080611666576040516312171d8360e31b815260040160405180910390fd5b6040518281527f6dd5bb8ebf4cfb647c1cc0e9364ed9ecbf56202f7d3c9f058473df82664478d89060200160405180910390a15050565b60046020525f9081526040902080546116b590614ad2565b80601f01602080910402602001604051908101604052809291908181526020018280546116e190614ad2565b801561172c5780601f106117035761010080835404028352916020019161172c565b820191905f5260205f20905b81548152906001019060200180831161170f57829003601f168201915b505050505081565b61173c6129fc565b601180546001600160a01b0319166001600160a01b0392909216919091179055565b6117688282612a57565b6111ef5760405163208e0a4160e11b815260040160405180910390fd5b61178d6129fc565b61179681612f64565b50565b61179633823461224e565b6117ac6129fc565b601154604080516375840fab60e01b815290515f926001600160a01b0316916375840fab9160048083019260209291908290030181865afa1580156117f3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118179190614b0a565b6001600160a01b03160361183e5760405163d92e233d60e01b815260040160405180910390fd5b5f54601154604080516375840fab60e01b815290516001600160a01b03938416936366e7ea0f9316916375840fab9160048083019260209291908290030181865afa15801561188f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118b39190614b0a565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044015f604051808303815f87803b1580156118f8575f5ffd5b505af115801561190a573d5f5f3e3d5ffd5b5050505080600d5f82825461191f9190614abf565b909155505050565b60115f9054906101000a90046001600160a01b03166001600160a01b031663c5f530af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611977573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061199b9190614b25565b3410156119bb5760405163047447a360e11b815260040160405180910390fd5b6042811415806119f4575081815f8181106119d8576119d8614b3c565b9050013560f81c60f81b6001600160f81b03191660c060f81b14155b15611a12576040516338497f4960e11b815260040160405180910390fd5b60135f611a1f8484612fcb565b6001600160a01b0316815260208101919091526040015f205415611a565760405163028aeb6760e21b815260040160405180910390fd5b611a61338383612ff7565b6111ef336005543461224e565b5f546001600160a01b03163314611a985760405163c78d372960e01b815260040160405180910390fd5b611aa48383835f613025565b61106d81613173565b611ab56129fc565b6014546001600160a01b03808316911603611ae357604051639b92bed360e01b815260040160405180910390fd5b601480546001600160a01b0319166001600160a01b0392909216919091179055565b5f818152600e6020908152604091829020600701805483518184028101840190945280845260609392830182828015611b5b57602002820191905f5260205f20905b815481526020019060010190808311611b47575b50505050509050919050565b6014546001600160a01b03163314611b925760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b038281165f90815260166020526040902054818316911603611bce5760405163eb81e1a360e01b815260040160405180910390fd5b806001600160a01b0316826001600160a01b031603611c005760405163367558c360e01b815260040160405180910390fd5b6001600160a01b039182165f90815260156020526040902080546001600160a01b03191691909216179055565b5f82815260026020526040902060040154611c5b57604051635926e0c360e01b815260040160405180910390fd5b5f8281526002602052604090206001810154905415611c7757505f5b5f5460405163520337df60e11b815260048101859052602481018390526001600160a01b039091169063a4066fbe906044015f604051808303815f87803b158015611cc0575f5ffd5b505af1158015611cd2573d5f5f3e3d5ffd5b50505050818015611ce257508015155b1561106d575f805484825260046020819052604092839020925163242a6e3f60e01b81526001600160a01b039092169263242a6e3f92611d259288929101614b50565b5f604051808303815f87803b158015611d3c575f5ffd5b505af1158015611d4e573d5f5f3e3d5ffd5b50505050505050565b336001600160a01b038216611d7f5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038181165f90815260156020526040902054811690831614611dbb57604051630fe3b3c160e31b815260040160405180910390fd5b6001600160a01b039081165f9081526016602090815260408083208054949095166001600160a01b031994851617909455601590529190912080549091169055565b5f546001600160a01b03163314611e275760405163c78d372960e01b815260040160405180910390fd5b5f600e5f611e33611507565b81526020019081526020015f2090505f5f90505b82811015611ea9575f848483818110611e6257611e62614b3c565b602090810292909201355f81815260028452604080822060010154948890529020839055600c860154909350611e9a91508290614abf565b600c8501555050600101611e47565b50611eb8600782018484614535565b50505050565b611ec66129fc565b601280546001600160a01b0319166001600160a01b0392909216919091179055565b5f546001600160a01b03163314611f125760405163c78d372960e01b815260040160405180910390fd5b5f600e5f611f1e611507565b81526020019081526020015f2090505f81600701805480602002602001604051908101604052809291908181526020018280548015611f7a57602002820191905f5260205f20905b815481526020019060010190808311611f66575b50505050509050611fff82828c8c808060200260200160405190810160405280939291908181526020018383602002808284375f81840152601f19601f820116905080830192505050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152506131e592505050565b600180545f908152600e60205260409020600881015490919042111561203157600882015461202e9042614bde565b90505b6120b1818584868c8c808060200260200160405190810160405280939291908181526020018383602002808284375f81840152601f19601f820116905080830192505050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152506133ff92505050565b6120f0818584868c8c808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250613b3992505050565b50506120fa611507565b6001554260088301554360098301556011546040805163d9a7c1f960e01b815290516001600160a01b039092169163d9a7c1f9916004808201926020929091908290030181865afa158015612151573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121759190614b25565b600b83015550600d80549101555050505050505050565b6121946129fc565b6001600160a01b0381166121c257604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61179681612d49565b5f6121d68383612a57565b506001600160a01b0383165f9081526009602090815260408083208584529091528120549081900361221b5760405163899aaa9d60e01b815260040160405180910390fd5b6001600160a01b0384165f90815260096020908152604080832086845290915281205561224781613173565b9392505050565b5f8281526002602052604090206004015461227c57604051635926e0c360e01b815260040160405180910390fd5b5f82815260026020526040902054156122a8576040516353670afb60e11b815260040160405180910390fd5b6122b58383836001613025565b6122be82613db7565b61106d5760405163c2eb4ead60e01b815260040160405180910390fd5b6001600160a01b038082165f90815260166020526040812054909116806114a9575090919050565b5f8281526002602052604090205415801561231d57508015155b15612344575f828152600260205260409020600101546007546123409190614bde565b6007555b5f828152600260205260409020548111156111ef575f8281526002602052604081208281556006015490036123d35761237b611507565b5f8381526002602090815260409182902060068101849055426005909101819055825193845290830152805184927fac4801c32a6067ff757446524ee4e7a373797278ac3c883eac5c693b4ad72e4792908290030190a25b817fcd35267e7654194727477d6c78b541a553483cff7f92a055d17868d3da6e953e826040516112e991815260200190565b6012546001600160a01b03161561106d576012546040516001600160a01b03858116602483015284811660448301525f921690627a12009060640160408051601f198184030181529181526020820180516001600160e01b0316631fbcb08360e11b179052516124759190614bf1565b5f604051808303815f8787f1925050503d805f81146124af576040519150601f19603f3d011682016040523d82523d5f602084013e6124b4565b606091505b50509050801580156124c35750815b15611eb8576040516347b4be6960e11b815260040160405180910390fd5b6124e9613e6e565b61179681613eb7565b611505613e6e565b6001600160a01b0384165f908152600b60209081526040808320868452825280832085845282528083208151606081018352815480825260018301549482019490945260029091015491810191909152910361256957604051630fe3b3c160e31b815260040160405180910390fd5b60208082015182515f8781526002909352604090922060050154909190158015906125a357505f8681526002602052604090206005015482115b156125c35750505f84815260026020526040902060058101546006909101545b60115f9054906101000a90046001600160a01b03166001600160a01b031663b82b84276040518163ffffffff1660e01b8152600401602060405180830381865afa158015612613573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126379190614b25565b6126419083614abf565b42101561266157604051635ada9a9960e01b815260040160405180910390fd5b60115f9054906101000a90046001600160a01b03166001600160a01b031663650acd666040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126b1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126d59190614b25565b6126df9082614abf565b6126e7611507565b1015612706576040516323ea994d60e01b815260040160405180910390fd5b6001600160a01b0387165f908152600b60209081526040808320898452825280832088845282528083206002908101548a855290835281842054600f9093529083205490926080909216151591906127619084908490613ebf565b6001600160a01b038b165f908152600b602090815260408083208d845282528083208c84529091528120818155600181018290556002015590508083116127bb576040516318f967fb60e01b815260040160405180910390fd5b5f6001600160a01b0388166127d08386614bde565b6040515f81818185875af1925050503d805f8114612809576040519150601f19603f3d011682016040523d82523d5f602084013e61280e565b606091505b5050905080612830576040516312171d8360e31b815260040160405180910390fd5b61283982612f64565b888a6001600160a01b038d167f94ffd6b85c71b847775c89ef6496b93cee961bdc6ff827fd117f174f06f745ae6128708689614bde565b60408051918252602082018890520160405180910390a45050505050505050505050565b306001600160a01b037f000000000000000000000000fc00face0000000000000000000000000000000116148061291a57507f000000000000000000000000fc00face000000000000000000000000000000016001600160a01b031661290e5f516020614eb75f395f51905f52546001600160a01b031690565b6001600160a01b031614155b156115055760405163703e46dd60e11b815260040160405180910390fd5b6117966129fc565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561299a575060408051601f3d908101601f1916820190925261299791810190614b25565b60015b6129c257604051634c9c8ce360e01b81526001600160a01b03831660048201526024016121b9565b5f516020614eb75f395f51905f5281146129f257604051632a87526960e21b8152600481018290526024016121b9565b61106d8383613f25565b33612a2e7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146115055760405163118cdaa760e01b81523360048201526024016121b9565b5f5f612a638484612cdf565b9050612a6e83613f7a565b6001600160a01b0385165f818152600a60209081526040808320888452825280832094909455918152600982528281208682529091529081208054839290612ab7908490614abf565b909155505015159392505050565b6001600160a01b0386165f908152600c6020908152604080832088845290915281208054869290612af7908490614bde565b90915550505f85815260026020526040902060010154612b18908590614bde565b5f86815260026020526040902060010155600654612b37908590614bde565b6006555f85815260026020526040902054612b5e5783600754612b5a9190614bde565b6007555b5f612b688661145d565b90508015801590612b8457505f86815260026020526040902054155b15612c645760115f9054906101000a90046001600160a01b03166001600160a01b031663c5f530af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bd9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bfd9190614b25565b811015612c2e578215612c235760405163047447a360e11b815260040160405180910390fd5b612c2e866001612303565b818015612c415750612c3f86613db7565b155b15612c5f5760405163c2eb4ead60e01b815260040160405180910390fd5b612c6f565b612c6f866001612303565b5f8681526002602081905260409091200154611d4e9088906001600160a01b031686612405565b306001600160a01b037f000000000000000000000000fc00face0000000000000000000000000000000116146115055760405163703e46dd60e11b815260040160405180910390fd5b6001600160a01b0382165f908152600a6020908152604080832084845290915281205481612d0c84613f7a565b6001600160a01b0386165f908152600c60209081526040808320888452909152812054919250612d3e82878686613fcf565b979650505050505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b6001600160a01b0389165f9081526003602052604090205415612def57604051633f4dc7d360e11b815260040160405180910390fd5b6001600160a01b0389165f8181526003602081815260408084208d90558c845260028083528185208b81559384018a905560048085018a90556005850188905560068501899055930180546001600160a01b0319169095179094555220612e57878983614c4b565b508760135f612e668a8a612fcb565b6001600160a01b03166001600160a01b031681526020019081526020015f2081905550886001600160a01b0316887f49bca1ed2666922f9f1690c26a569e1299c2a715fe57647d77e81adfabbf25bf8686604051612ece929190918252602082015260400190565b60405180910390a38115612f1857604080518381526020810183905289917fac4801c32a6067ff757446524ee4e7a373797278ac3c883eac5c693b4ad72e47910160405180910390a25b8415612f5957877fcd35267e7654194727477d6c78b541a553483cff7f92a055d17868d3da6e953e86604051612f5091815260200190565b60405180910390a25b505050505050505050565b8015611796576040515f9082156108fc0290839083818181858288f19350505050158015612f94573d5f5f3e3d5ffd5b506040518181527f8918bd6046d08b314e457977f29562c5d76a7030d79b1edba66e8a5da0b77ae89060200160405180910390a150565b5f612fd98260028186614d04565b604051612fe7929190614d2b565b6040519081900390209392505050565b5f60055f815461300690614d3a565b91829055509050611eb8848285855f61301d611507565b425f5f612db9565b815f0361304557604051631f2a200560e01b815260040160405180910390fd5b61304f8484612a57565b506001600160a01b0384165f908152600c6020908152604080832086845290915290205461307e908390614abf565b6001600160a01b0385165f908152600c602090815260408083208784528252808320939093556002905220600101546130b78382614abf565b5f858152600260205260409020600101556006546130d6908490614abf565b6006555f848152600260205260409020546130fd57826007546130f99190614abf565b6007555b613108848215611c2d565b83856001600160a01b03167f9a8f44850296624dadfd9c246d17e47171d35727a181bd090aa14bbbe00238bb8560405161314491815260200190565b60405180910390a35f84815260026020819052604090912001546115679086906001600160a01b031684612405565b5f546040516366e7ea0f60e01b8152306004820152602481018390526001600160a01b03909116906366e7ea0f906044015f604051808303815f87803b1580156131bb575f5ffd5b505af11580156131cd573d5f5f3e3d5ffd5b5050505080600d546131df9190614abf565b600d5550565b5f5b83518110156115675760115f9054906101000a90046001600160a01b03166001600160a01b0316635a68f01a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613240573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906132649190614b25565b82828151811061327657613276614b3c565b6020026020010151118015613316575060115f9054906101000a90046001600160a01b03166001600160a01b031662cc7f836040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132d5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906132f99190614b25565b83828151811061330b5761330b614b3c565b602002602001015110155b156133625761333f84828151811061333057613330614b3c565b60200260200101516008612303565b61336284828151811061335457613354614b3c565b60200260200101515f611c2d565b82818151811061337457613374614b3c565b6020026020010151856005015f86848151811061339357613393614b3c565b602002602001015181526020019081526020015f20819055508181815181106133be576133be614b3c565b6020026020010151856006015f8684815181106133dd576133dd614b3c565b60209081029190910181015182528101919091526040015f20556001016131e7565b5f6040518060a0016040528085516001600160401b0381111561342457613424614685565b60405190808252806020026020018201604052801561344d578160200160208202803683370190505b5081526020015f815260200185516001600160401b0381111561347257613472614685565b60405190808252806020026020018201604052801561349b578160200160208202803683370190505b5081526020015f81526020015f81525090505f5f90505b84518110156135db575f866004015f8784815181106134d3576134d3614b3c565b602002602001015181526020019081526020015f205490505f5f90508185848151811061350257613502614b3c565b60200260200101511115613538578185848151811061352357613523614b3c565b60200260200101516135359190614bde565b90505b8986848151811061354b5761354b614b3c565b60200260200101518261355e9190614d52565b6135689190614d7d565b8460400151848151811061357e5761357e614b3c565b602002602001018181525050836040015183815181106135a0576135a0614b3c565b602002602001015184606001516135b79190614abf565b606085015260808401516135cc908290614abf565b608085015250506001016134b2565b505f5b84518110156136c857878482815181106135fa576135fa614b3c565b60200260200101518986848151811061361557613615614b3c565b60200260200101518a5f015f8a878151811061363357613633614b3c565b602002602001015181526020019081526020015f20546136539190614d52565b61365d9190614d7d565b6136679190614d52565b6136719190614d7d565b825180518390811061368557613685614b3c565b602090810291909101015281518051829081106136a4576136a4614b3c565b602002602001015182602001516136bb9190614abf565b60208301526001016135de565b505f5b84518110156139cc575f6137738960115f9054906101000a90046001600160a01b03166001600160a01b031663d9a7c1f96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613729573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061374d9190614b25565b855180518690811061376157613761614b3c565b60200260200101518660200151614038565b90506137a583608001518460400151848151811061379357613793614b3c565b60200260200101518560600151614073565b6137af9082614abf565b90505f8683815181106137c4576137c4614b3c565b6020908102919091018101515f8181526002808452604080832090910154601154825163a778651560e01b815292519496506001600160a01b0391821695939461385c948994929093169263a778651592600480820193918290030181865afa158015613833573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138579190614b25565b6141c4565b6001600160a01b0383165f908152600c6020908152604080832087845290915290205490915080156138c0576001600160a01b0383165f908152600960209081526040808320878452909152812080548492906138ba908490614abf565b90915550505b5f6138cb8387614bde565b5f86815260026020526040812060010154919250811561390557816138f8670de0b6b3a764000085614d52565b6139029190614d7d565b90505b5f87815260018f016020526040902054613920908290614abf565b8f6001015f8981526020019081526020015f20819055508a898151811061394957613949614b3c565b60200260200101518f6004015f8981526020019081526020015f20819055508b898151811061397a5761397a614b3c565b60200260200101518e6002015f8981526020019081526020015f20546139a09190614abf565b8f6002015f8981526020019081526020015f2081905550505050505050505080806001019150506136cb565b506080810151600a8701819055600d541115613a025785600a0154600d5f8282546139f79190614bde565b90915550613a079050565b5f600d555b6010546001600160a01b031615611d4e575f670de0b6b3a764000060115f9054906101000a90046001600160a01b03166001600160a01b03166394c3e9146040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a72573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613a969190614b25565b8360800151613aa59190614d52565b613aaf9190614d7d565b9050613aba81613173565b6010546040515f916001600160a01b031690620f424090849084818181858888f193505050503d805f8114613b0a576040519150601f19603f3d011682016040523d82523d5f602084013e613b0f565b606091505b5050905080612f59578160085f828254613b299190614abf565b9091555050505050505050505050565b5f5b8251811015613daf575f838281518110613b5757613b57614b3c565b602002602001015190505f87613b72670de0b6b3a764000090565b858581518110613b8457613b84614b3c565b6020026020010151613b969190614d52565b613ba09190614d7d565b9050670de0b6b3a7640000811115613bbd5750670de0b6b3a76400005b5f8281526003870160209081526040808320815160608101835290546001600160401b038116825263ffffffff600160401b8204811694830194909452600160601b90049092169082015290613c1383836141e2565b5f85815260038b0160209081526040918290208351815485840151868601516001600160401b039093166bffffffffffffffffffffffff1990921691909117600160401b63ffffffff928316021763ffffffff60601b1916600160601b91909216021790556011548251631c25433760e01b815292519394506001600160a01b031692631c2543379260048082019392918290030181865afa158015613cbb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613cdf9190614d90565b6001600160401b0316815f01516001600160401b0316108015613d85575060115f9054906101000a90046001600160a01b03166001600160a01b0316633fa225486040518163ffffffff1660e01b8152600401602060405180830381865afa158015613d4d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613d719190614db6565b63ffffffff16816040015163ffffffff1610155b15613d9f57613d95846010612303565b613d9f845f611c2d565b505060019092019150613b3b9050565b505050505050565b5f670de0b6b3a764000060115f9054906101000a90046001600160a01b03166001600160a01b0316632265f2846040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e11573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e359190614b25565b613e3e8461145d565b613e489190614d52565b613e529190614d7d565b5f92835260026020526040909220600101549190911115919050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661150557604051631afcd79f60e31b815260040160405180910390fd5b612194613e6e565b5f821580613ed55750670de0b6b3a76400008210155b15613ee157505f612247565b670de0b6b3a7640000613ef48382614bde565b613efe9086614d52565b613f089190614d7d565b613f13906001614abf565b90508381111561224757509192915050565b613f2e826143c5565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115613f725761106d8282614428565b6111ef614491565b5f8181526002602052604081206006015415613fc7575f828152600260205260409020600601546001541015613fb257505060015490565b505f9081526002602052604090206006015490565b505060015490565b5f818310613fde57505f6114ec565b5f838152600e6020818152604080842088855260019081018352818520548786529383528185208986520190915290912054670de0b6b3a7640000876140248484614bde565b61402e9190614d52565b612d3e9190614d7d565b5f825f0361404757505f6114ec565b5f6140528587614d52565b90508261405f8583614d52565b6140699190614d7d565b9695505050505050565b5f825f0361408257505f612247565b5f8261408e8587614d52565b6140989190614d7d565b9050670de0b6b3a764000060115f9054906101000a90046001600160a01b03166001600160a01b03166394c3e9146040518163ffffffff1660e01b8152600401602060405180830381865afa1580156140f3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906141179190614b25565b60115f9054906101000a90046001600160a01b03166001600160a01b031663c74dd6216040518163ffffffff1660e01b8152600401602060405180830381865afa158015614167573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061418b9190614b25565b61419d90670de0b6b3a7640000614bde565b6141a79190614bde565b6141b19083614d52565b6141bb9190614d7d565b95945050505050565b5f670de0b6b3a76400006141d88385614d52565b6122479190614d7d565b604080516060810182525f8082526020820181905291810191909152604080516060810182525f8082526020820181905291810191909152826040015163ffffffff165f03614245576001600160401b03841681526001604082015290506114a9565b5f836040015160016142579190614dd9565b63ffffffff1690505f846020015163ffffffff16866001600160401b0316865f01516001600160401b031660018561428f9190614df5565b6142999190614e14565b6142a39190614e3d565b6142ad9190614e3d565b90506142b98282614e5c565b6001600160401b031683526142ce8282614e89565b63ffffffff166020840152670de0b6b3a764000083516001600160401b031611156142ff57670de0b6b3a764000083525b60115f9054906101000a90046001600160a01b03166001600160a01b0316633fa225486040518163ffffffff1660e01b8152600401602060405180830381865afa15801561434f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906143739190614db6565b63ffffffff16856040015163ffffffff1610156143aa57604085015161439a906001614dd9565b63ffffffff1660408401526143bb565b60408086015163ffffffff16908401525b5090949350505050565b806001600160a01b03163b5f036143fa57604051634c9c8ce360e01b81526001600160a01b03821660048201526024016121b9565b5f516020614eb75f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f5f846001600160a01b0316846040516144449190614bf1565b5f60405180830381855af49150503d805f811461447c576040519150601f19603f3d011682016040523d82523d5f602084013e614481565b606091505b50915091506141bb8583836144b0565b34156115055760405163b398979f60e01b815260040160405180910390fd5b6060826144c5576144c08261450c565b612247565b81511580156144dc57506001600160a01b0384163b155b1561450557604051639996b31560e01b81526001600160a01b03851660048201526024016121b9565b5080612247565b80511561451c5780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b828054828255905f5260205f2090810192821561456e579160200282015b8281111561456e578235825591602001919060010190614553565b5061457a92915061457e565b5090565b5b8082111561457a575f815560010161457f565b6001600160a01b0381168114611796575f5ffd5b5f602082840312156145b6575f5ffd5b813561224781614592565b5f602082840312156145d1575f5ffd5b5035919050565b5f5f604083850312156145e9575f5ffd5b50508035926020909101359150565b5f5f5f6060848603121561460a575f5ffd5b833561461581614592565b95602085013595506040909401359392505050565b5f5f5f5f5f60a0868803121561463e575f5ffd5b8535945060208601359350604086013561465781614592565b9250606086013561466781614592565b9150608086013561467781614592565b809150509295509295909350565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156146aa575f5ffd5b82356146b581614592565b915060208301356001600160401b038111156146cf575f5ffd5b8301601f810185136146df575f5ffd5b80356001600160401b038111156146f8576146f8614685565b604051601f8201601f19908116603f011681016001600160401b038111828210171561472657614726614685565b60405281815282820160200187101561473d575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f5f5f6060848603121561476e575f5ffd5b505081359360208301359350604090920135919050565b5f5f60408385031215614796575f5ffd5b82356147a181614592565b946020939093013593505050565b5f5f83601f8401126147bf575f5ffd5b5081356001600160401b038111156147d5575f5ffd5b6020830191508360208285010111156147ec575f5ffd5b9250929050565b5f5f5f5f5f60808688031215614807575f5ffd5b853561481281614592565b94506020860135935060408601356001600160401b03811115614833575f5ffd5b61483f888289016147af565b96999598509660600135949350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6122476020830184614851565b5f5f602083850312156148a2575f5ffd5b82356001600160401b038111156148b7575f5ffd5b6148c3858286016147af565b90969095509350505050565b602080825282518282018190525f918401906040840190835b818110156149065783518352602093840193909201916001016148e8565b509095945050505050565b5f5f60408385031215614922575f5ffd5b823561492d81614592565b9150602083013561493d81614592565b809150509250929050565b5f5f60408385031215614959575f5ffd5b823591506020830135801515811461493d575f5ffd5b5f5f83601f84011261497f575f5ffd5b5081356001600160401b03811115614995575f5ffd5b6020830191508360208260051b85010111156147ec575f5ffd5b5f5f602083850312156149c0575f5ffd5b82356001600160401b038111156149d5575f5ffd5b6148c38582860161496f565b5f5f5f5f5f5f5f5f6080898b0312156149f8575f5ffd5b88356001600160401b03811115614a0d575f5ffd5b614a198b828c0161496f565b90995097505060208901356001600160401b03811115614a37575f5ffd5b614a438b828c0161496f565b90975095505060408901356001600160401b03811115614a61575f5ffd5b614a6d8b828c0161496f565b90955093505060608901356001600160401b03811115614a8b575f5ffd5b614a978b828c0161496f565b999c989b5096995094979396929594505050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156114a9576114a9614aab565b600181811c90821680614ae657607f821691505b602082108103614b0457634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215614b1a575f5ffd5b815161224781614592565b5f60208284031215614b35575f5ffd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b828152604060208201525f5f8354614b6781614ad2565b806040860152600182165f8114614b855760018114614ba157614bd2565b60ff1983166060870152606082151560051b8701019350614bd2565b865f5260205f205f5b83811015614bc957815488820160600152600190910190602001614baa565b87016060019450505b50919695505050505050565b818103818111156114a9576114a9614aab565b5f82518060208501845e5f920191825250919050565b601f82111561106d57805f5260205f20601f840160051c81016020851015614c2c5750805b601f840160051c820191505b81811015611567575f8155600101614c38565b6001600160401b03831115614c6257614c62614685565b614c7683614c708354614ad2565b83614c07565b5f601f841160018114614ca7575f8515614c905750838201355b5f19600387901b1c1916600186901b178355611567565b5f83815260208120601f198716915b82811015614cd65786850135825560209485019460019092019101614cb6565b5086821015614cf2575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b5f5f85851115614d12575f5ffd5b83861115614d1e575f5ffd5b5050820193919092039150565b818382375f9101908152919050565b5f60018201614d4b57614d4b614aab565b5060010190565b80820281158282048414176114a9576114a9614aab565b634e487b7160e01b5f52601260045260245ffd5b5f82614d8b57614d8b614d69565b500490565b5f60208284031215614da0575f5ffd5b81516001600160401b0381168114612247575f5ffd5b5f60208284031215614dc6575f5ffd5b815163ffffffff81168114612247575f5ffd5b63ffffffff81811683821601908111156114a9576114a9614aab565b6001600160801b0382811682821603908111156114a9576114a9614aab565b6001600160801b038181168382160290811690818114614e3657614e36614aab565b5092915050565b6001600160801b0381811683821601908111156114a9576114a9614aab565b5f6001600160801b03831680614e7457614e74614d69565b806001600160801b0384160491505092915050565b5f6001600160801b03831680614ea157614ea1614d69565b806001600160801b038416069150509291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122066d19146273283f0e3b105875ee752668c5f6172f37ee249748d1d959cb7042564736f6c634300081b0033
Deployed Bytecode Sourcemap
683:46356:22:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9529:21;;-1:-1:-1;;;9529:21:22;;;;;;;;;;;683:46356;;;;1615:66;;;;;;;;;;-1:-1:-1;1615:66:22;;;;;:::i;:::-;;;;;;;;;;;;;;;;;548:25:27;;;536:2;521:18;1615:66:22;;;;;;;;20392:288;;;;;;;;;;-1:-1:-1;20392:288:22;;;;;:::i;:::-;;:::i;:::-;;5121:37;;;;;;;;;;-1:-1:-1;5121:37:22;;;;-1:-1:-1;;;;;5121:37:22;;;;;;-1:-1:-1;;;;;979:32:27;;;961:51;;949:2;934:18;5121:37:22;815:203:27;18717:462:22;;;;;;;;;;-1:-1:-1;18717:462:22;;;;;:::i;:::-;;:::i;4604:26::-;;;;;;;;;;;;;;;;16267:414;;;;;;;;;;-1:-1:-1;16267:414:22;;;;;:::i;:::-;;:::i;2735:140::-;;;;;;;;;;-1:-1:-1;2735:140:22;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2068:25:27;;;2124:2;2109:18;;2102:34;;;;2152:18;;;2145:34;2056:2;2041:18;2735:140:22;1866:319:27;1975:31:22;;;;;;;;;;;;;;;;4671:63;;;;;;;;;;-1:-1:-1;4671:63:22;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2477:25:27;;;2533:2;2518:18;;2511:34;;;;2561:18;;;2554:34;;;;2619:2;2604:18;;2597:34;2662:3;2647:19;;2640:35;2706:3;2691:19;;2684:35;2464:3;2449:19;4671:63:22;2190:535:27;8764:460:22;;;;;;;;;;-1:-1:-1;8764:460:22;;;;;:::i;:::-;;:::i;16009:146::-;;;;;;;;;;-1:-1:-1;16009:146:22;;;;;:::i;:::-;;:::i;5458:75::-;;;;;;;;;;-1:-1:-1;5458:75:22;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;5458:75:22;;;10140:108;;;;;;;;;;-1:-1:-1;10140:108:22;;;;;:::i;:::-;;:::i;4161:214:2:-;;;;;;:::i;:::-;;:::i;15292:412:22:-;;;;;;;;;;-1:-1:-1;15292:412:22;;;;;:::i;:::-;;:::i;19437:807::-;;;;;;;;;;-1:-1:-1;19437:807:22;;;;;:::i;:::-;;:::i;3708:134:2:-;;;;;;;;;;;;;:::i;252:97:26:-;;;;;;;;;;-1:-1:-1;252:97:26;;-1:-1:-1;;;5519:50:27;;5507:2;5492:18;252:97:26;5375:200:27;20869:150:22;;;;;;;;;;-1:-1:-1;20869:150:22;;;;;:::i;:::-;;:::i;21279:171::-;;;;;;;;;;-1:-1:-1;21279:171:22;;;;;:::i;:::-;;:::i;23583:232::-;;;;;;;;;;-1:-1:-1;23583:232:22;;;;;:::i;:::-;;:::i;21531:195::-;;;;;;;;;;-1:-1:-1;21531:195:22;;;;;:::i;:::-;21631:7;21657:23;;;:16;:23;;;;;;;;:62;;;:49;;;;:62;;;;;;21531:195;19234:153;;;;;;;;;;-1:-1:-1;19234:153:22;;;;;:::i;:::-;-1:-1:-1;;;;;19343:24:22;;;;19317:7;19343:24;;;:13;:24;;;;;;;;:37;;;;;;;;;19234:153;3155:101:0;;;;;;;;;;;;;:::i;5581:68:22:-;;;;;;;;;;-1:-1:-1;5581:68:22;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;5581:68:22;;;20724:100;;;;;;;;;;;;;:::i;13616:557::-;;;;;;;;;;-1:-1:-1;13616:557:22;;;;;:::i;:::-;;:::i;1509:33::-;;;;;;;;;;;;;;;;18145:97;;;;;;;;;;-1:-1:-1;18145:97:22;;;;;:::i;:::-;;:::i;17011:580::-;;;;;;;;;;;;;:::i;1687:70::-;;;;;;;;;;-1:-1:-1;1687:70:22;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;18279:99::-;;;;;;;;;;-1:-1:-1;18279:99:22;;;;;:::i;:::-;;:::i;1876:25::-;;;;;;;;;;;;;;;;16726:183;;;;;;;;;;-1:-1:-1;16726:183:22;;;;;:::i;:::-;;:::i;2075:37::-;;;;;;;;;;;;;;;;2441:144:0;;;;;;;;;;-1:-1:-1;1313:22:0;2570:8;-1:-1:-1;;;;;2570:8:0;2441:144;;17667:85:22;;;;;;;;;;-1:-1:-1;17667:85:22;;;;;:::i;:::-;;:::i;15749:122::-;;;;;;:::i;:::-;;:::i;22808:171::-;;;;;;;;;;-1:-1:-1;22808:171:22;;;;;:::i;:::-;22896:7;22922:23;;;:16;:23;;;;;;;;:50;;;:37;;;;:50;;;;;;22808:171;17853:253;;;;;;;;;;-1:-1:-1;17853:253:22;;;;;:::i;:::-;;:::i;14617:511::-;;;;;;:::i;:::-;;:::i;2395:107::-;;;;;;;;;;-1:-1:-1;2395:107:22;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;14293:209;;;;;;;;;;-1:-1:-1;14293:209:22;;;;;:::i;:::-;;:::i;22043:184::-;;;;;;;;;;-1:-1:-1;22043:184:22;;;;;:::i;:::-;22131:6;22156:23;;;:16;:23;;;;;;;;:50;;;:37;;;;:50;;;;:64;-1:-1:-1;;;;;22156:64:22;;22043:184;;;;-1:-1:-1;;;;;8185:31:27;;;8167:50;;8155:2;8140:18;22043:184:22;8023:200:27;1819:58:2;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1819:58:2;;;;;9630:206:22;;;;;;;;;;-1:-1:-1;9630:206:22;;;;;:::i;:::-;;:::i;1548:61::-;;;;;;;;;;-1:-1:-1;1548:61:22;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1548:61:22;;;;;;;;;;;;;;8767:25:27;;;8823:2;8808:18;;8801:34;;;;-1:-1:-1;;;;;8871:32:27;;;8851:18;;;8844:60;;;;8935:2;8920:18;;8913:34;;;;8978:3;8963:19;;8956:35;8891:3;9007:19;;9000:35;;;;9066:3;9051:19;;9044:35;8754:3;8739:19;1548:61:22;8452:633:27;21068:144:22;;;;;;;;;;-1:-1:-1;21068:144:22;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;23321:143::-;;;;;;;;;;-1:-1:-1;23321:143:22;;;;;:::i;:::-;23382:4;23405:25;;;:12;:25;;;;;:32;995:6;23405:47;:52;;;23321:143;;;;9871:14:27;;9864:22;9846:41;;9834:2;9819:18;23321:143:22;9706:187:27;4988:30:22;;;;;;;;;;-1:-1:-1;4988:30:22;;;;-1:-1:-1;;;;;4988:30:22;;;4821:78;;;;;;;;;;-1:-1:-1;4821:78:22;;;;;:::i;:::-;;;;;;;;;;;;;;1764:30;;;;;;;;;;;;;;;;10426:372;;;;;;;;;;-1:-1:-1;10426:372:22;;;;;:::i;:::-;;:::i;45704:565::-;;;;;;;;;;-1:-1:-1;45704:565:22;;;;;:::i;:::-;;:::i;2932:91::-;;;;;;;;;;-1:-1:-1;2932:91:22;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;18562;;;;;;;;;;-1:-1:-1;18644:1:22;;-1:-1:-1;;;;;18644:1:22;18562:91;;10937:340;;;;;;;;;;-1:-1:-1;10937:340:22;;;;;:::i;:::-;;:::i;23026:127::-;;;;;;;;;;-1:-1:-1;23026:127:22;;;;;:::i;:::-;23088:7;23114:23;;;:16;:23;;;;;:32;;;;23026:127;22310:199;;;;;;;;;;-1:-1:-1;22310:199:22;;;;;:::i;:::-;22412:7;22438:23;;;:16;:23;;;;;;;;:64;;;:51;;;;:64;;;;;;22310:199;21797:179;;;;;;;;;;-1:-1:-1;21797:179:22;;;;;:::i;:::-;21889:7;21915:23;;;:16;:23;;;;;;;;:54;;;:41;;;;:54;;;;;;21797:179;12894:603;;;;;;;;;;-1:-1:-1;12894:603:22;;;;;:::i;:::-;;:::i;22574:167::-;;;;;;;;;;-1:-1:-1;22574:167:22;;;;;:::i;:::-;22660:7;22686:23;;;:16;:23;;;;;;;;:48;;;:35;;;;:48;;;;;;22574:167;18417:111;;;;;;;;;;-1:-1:-1;18417:111:22;;;;;:::i;:::-;;:::i;5374:36::-;;;;;;;;;;-1:-1:-1;5374:36:22;;;;-1:-1:-1;;;;;5374:36:22;;;11579:1146;;;;;;;;;;-1:-1:-1;11579:1146:22;;;;;:::i;:::-;;:::i;3405:215:0:-;;;;;;;;;;-1:-1:-1;3405:215:0;;;;;:::i;:::-;;:::i;5230:87:22:-;;;;;;;;;;-1:-1:-1;5230:87:22;;;;;:::i;:::-;;;;;;;;;;;;;;20392:288;20476:10;20456:17;20514:39;20476:10;20539:13;20514;:39::i;:::-;20496:57;;20564:44;20574:9;20585:13;20600:7;20564:9;:44::i;:::-;20650:13;20639:9;-1:-1:-1;;;;;20623:50:22;;20665:7;20623:50;;;;548:25:27;;536:2;521:18;;402:177;20623:50:22;;;;;;;;20446:234;;20392:288;:::o;18717:462::-;18799:10;18779:17;18837:39;18799:10;18862:13;18837;:39::i;:::-;18819:57;;18977:9;18992:22;19004:9;18992:11;:22::i;:::-;-1:-1:-1;;;;;18992:27:22;19027:7;18992:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18976:63;;;19054:4;19049:59;;19081:16;;-1:-1:-1;;;19081:16:22;;;;;;;;;;;19049:59;19149:13;19138:9;-1:-1:-1;;;;;19123:49:22;;19164:7;19123:49;;;;548:25:27;;536:2;521:18;;402:177;19123:49:22;;;;;;;;18769:410;;;18717:462;:::o;16267:414::-;24302:4;24341;-1:-1:-1;;;;;24341:4:22;8398:10;24325:21;8386:72;;8432:15;;-1:-1:-1;;;8432:15:22;;;;;;;;;;;8386:72;16367:6;16363:79:::1;;16409:22;;-1:-1:-1::0;;;16409:22:22::1;;;;;;;;;;;16363:79;16452:45;16477:11;16490:6;16452:24;:45::i;:::-;16507:34;16522:11;16535:5;16507:14;:34::i;:::-;16551:21;16575:25:::0;;;:12:::1;:25;::::0;;;;;;:30:::1;::::0;-1:-1:-1;;;;;16575:30:22::1;::::0;16615:59:::1;::::0;16575:30;;;;16615:22:::1;:59::i;:::-;16353:328;16267:414:::0;;:::o;8764:460::-;8870:21:1;4302:15;;-1:-1:-1;;;4302:15:1;;;;4301:16;;-1:-1:-1;;;;;4348:14:1;4158:30;4726:16;;:34;;;;;4746:14;4726:34;4706:54;;4770:17;4790:11;-1:-1:-1;;;;;4790:16:1;4805:1;4790:16;:50;;;;-1:-1:-1;4818:4:1;4810:25;:30;4790:50;4770:70;;4856:12;4855:13;:30;;;;;4873:12;4872:13;4855:30;4851:91;;;4908:23;;-1:-1:-1;;;4908:23:1;;;;;;;;;;;4851:91;4951:18;;-1:-1:-1;;4951:18:1;4968:1;4951:18;;;4979:67;;;;5013:22;;-1:-1:-1;;;;5013:22:1;-1:-1:-1;;;5013:22:1;;;4979:67;8951:21:22::1;8966:5;8951:14;:21::i;:::-;8982:24;:22;:24::i;:::-;9016:18;:32:::0;;;9058:4:::1;:33:::0;;-1:-1:-1;;;;;9058:33:22;;::::1;-1:-1:-1::0;;;;;;9058:33:22;;::::1;;::::0;;;9101:1:::1;:24:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;9135:11:::1;:26:::0;;;9211:6:::1;46983:15:::0;;46910:95;9211:6:::1;9171:29;::::0;;;:16:::1;:29;::::0;;;;:37:::1;;:46:::0;5066:101:1;;;;5100:23;;-1:-1:-1;;;;5100:23:1;;;5142:14;;-1:-1:-1;8167:50:27;;5142:14:1;;8155:2:27;8140:18;5142:14:1;;;;;;;5066:101;4092:1081;;;;;8764:460:22;;;;;:::o;16009:146::-;16081:67;16091:10;16103:13;16118:4;16124:23;16136:10;16124:11;:23::i;:::-;16081:9;:67::i;:::-;16009:146;;:::o;10140:108::-;10205:36;;-1:-1:-1;;;;;10205:36:22;;;10226:10;;10205:36;;;;;10140:108;:::o;4161:214:2:-;2655:13;:11;:13::i;:::-;4276:36:::1;4294:17;4276;:36::i;:::-;4322:46;4344:17;4363:4;4322:21;:46::i;15292:412:22:-:0;2334:13:0;:11;:13::i;:::-;23382:4:22;23405:25;;;:12;:25;;;;;:32;995:6;23405:47;15398:82:::1;;15448:21;;-1:-1:-1::0;;;15448:21:22::1;;;;;;;;;;;15398:82;262:4:13::0;15493:11:22::1;:28;15489:86;;;15544:20;;-1:-1:-1::0;;;15544:20:22::1;;;;;;;;;;;15489:86;15584:32;::::0;;;:19:::1;:32;::::0;;;;;;:46;;;15645:52;15604:11;;15645:52:::1;::::0;::::1;::::0;15619:11;548:25:27;;536:2;521:18;;402:177;15645:52:22::1;;;;;;;;15292:412:::0;;:::o;19437:807::-;19547:10;19568:39;19547:10;19593:13;19568;:39::i;:::-;;19622:6;19632:1;19622:11;19618:61;;19656:12;;-1:-1:-1;;;19656:12:22;;;;;;;;;;;19618:61;-1:-1:-1;;;;;19693:31:22;;;;;;:20;:31;;;;;;;;:46;;;;;;;;:52;;;;;;;;:59;;;:64;19689:117;;19780:15;;-1:-1:-1;;;19780:15:22;;;;;;;;;;;19689:117;19816:67;19831:9;19842:13;19857:6;19865:4;19871:5;19878:4;19816:14;:67::i;:::-;-1:-1:-1;;;;;19894:31:22;;;;;;:20;:31;;;;;;;;:46;;;;;;;;:52;;;;;;;;:59;;:68;;;20033:14;:12;:14::i;:::-;-1:-1:-1;;;;;19972:31:22;;;;;;:20;:31;;;;;;;;:46;;;;;;;;:52;;;;;;;;:75;;;46983:15;20057:57;;;;:66;;;;20134:36;;19972:46;;20134:14;:36::i;:::-;20224:4;20209:13;20198:9;-1:-1:-1;;;;;20186:51:22;;20230:6;20186:51;;;;548:25:27;;536:2;521:18;;402:177;20186:51:22;;;;;;;;19517:727;19437:807;;;:::o;3708:134:2:-;3777:7;2926:20;:18;:20::i;:::-;-1:-1:-1;;;;;;;;;;;;3708:134:2;:::o;20869:150:22:-;20933:7;20968:25;;;:12;:25;;;;;;;;:30;;;;-1:-1:-1;;;;;20968:30:22;20959:40;;:8;:40;;;;;:53;;;;;;;;;;20869:150::o;21279:171::-;21367:7;21393:23;;;:16;:23;;;;;;;;:50;;;;;;;;;21279:171;;;;;:::o;23583:232::-;23670:7;23689:14;23706:37;23718:9;23729:13;23706:11;:37::i;:::-;-1:-1:-1;;;;;23760:24:22;;;;;;:13;:24;;;;;;;;:39;;;;;;;;;23689:54;;-1:-1:-1;23760:48:22;;23689:54;;23760:48;:::i;:::-;23753:55;23583:232;-1:-1:-1;;;;23583:232:22:o;3155:101:0:-;2334:13;:11;:13::i;:::-;3219:30:::1;3246:1;3219:18;:30::i;:::-;3155:101::o:0;20724:100:22:-;20769:7;20795:18;;20816:1;20795:22;;;;:::i;:::-;20788:29;;20724:100;:::o;13616:557::-;24302:4;24341;-1:-1:-1;;;;;24341:4:22;8398:10;24325:21;8386:72;;8432:15;;-1:-1:-1;;;8432:15:22;;;;;;;;;;;8386:72;13792:276:::1;13825:4;13843:11;13868:6;;788:1;13911;13942:11;13967:1;14020;13792:19;:276::i;:::-;14096:15;;14082:11;:29;14078:89;;;14127:15;:29:::0;;;14078:89:::1;13616:557:::0;;;;;:::o;18145:97::-;2334:13:0;:11;:13::i;:::-;18216:15:22::1;:19:::0;;-1:-1:-1;;;;;;18216:19:22::1;-1:-1:-1::0;;;;;18216:19:22;;;::::1;::::0;;;::::1;::::0;;18145:97::o;17011:580::-;17065:15;;-1:-1:-1;;;;;17065:15:22;17061:83;;17117:16;;-1:-1:-1;;;17117:16:22;;;;;;;;;;;17061:83;17157:22;;17183:1;17157:27;17153:91;;17207:26;;-1:-1:-1;;;17207:26:22;;;;;;;;;;;17153:91;17332:22;;;17317:12;17364:26;;;;17420:15;;:51;;17332:22;;17317:12;-1:-1:-1;;;;;17420:15:22;;;;17459:7;;17332:22;;17317:12;17420:51;17317:12;17420:51;17332:22;17420:15;17459:7;17420:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17401:70;;;17486:7;17481:62;;17516:16;;-1:-1:-1;;;17516:16:22;;;;;;;;;;;17481:62;17558:26;;548:25:27;;;17558:26:22;;536:2:27;521:18;17558:26:22;;;;;;;17051:540;;17011:580::o;1687:70::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;18279:99::-;2334:13:0;:11;:13::i;:::-;18348:1:22::1;:23:::0;;-1:-1:-1;;;;;;18348:23:22::1;-1:-1:-1::0;;;;;18348:23:22;;;::::1;::::0;;;::::1;::::0;;18279:99::o;16726:183::-;16814:39;16828:9;16839:13;16814;:39::i;:::-;16809:94;;16876:16;;-1:-1:-1;;;16876:16:22;;;;;;;;;;;17667:85;2334:13:0;:11;:13::i;:::-;17729:16:22::1;17738:6;17729:8;:16::i;:::-;17667:85:::0;:::o;15749:122::-;15817:47;15827:10;15839:13;15854:9;15817;:47::i;17853:253::-;2334:13:0;:11;:13::i;:::-;17923:1:22::1;::::0;:25:::1;::::0;;-1:-1:-1;;;17923:25:22;;;;17960:1:::1;::::0;-1:-1:-1;;;;;17923:1:22::1;::::0;:23:::1;::::0;:25:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:1;:25:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;17923:39:22::1;::::0;17919:90:::1;;17985:13;;-1:-1:-1::0;;;17985:13:22::1;;;;;;;;;;;17919:90;18018:4;::::0;18034:1:::1;::::0;:25:::1;::::0;;-1:-1:-1;;;18034:25:22;;;;-1:-1:-1;;;;;18018:4:22;;::::1;::::0;:15:::1;::::0;18034:1:::1;::::0;:23:::1;::::0;:25:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:1;:25:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;18018:50;::::0;-1:-1:-1;;;;;;18018:50:22::1;::::0;;;;;;-1:-1:-1;;;;;14460:32:27;;;18018:50:22::1;::::0;::::1;14442:51:27::0;14509:18;;;14502:34;;;14415:18;;18018:50:22::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18093:6;18078:11;;:21;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;;17853:253:22:o;14617:511::-;14708:1;;;;;;;;;-1:-1:-1;;;;;14708:1:22;-1:-1:-1;;;;;14708:14:22;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14696:9;:28;14692:89;;;14747:23;;-1:-1:-1;;;14747:23:22;;;;;;;;;;;14692:89;14811:2;14794:19;;;;:40;;;14817:6;;14824:1;14817:9;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;;;;14817:17:22;;14830:4;14817:17;;;;14794:40;14790:95;;;14857:17;;-1:-1:-1;;;14857:17:22;;;;;;;;;;;14790:95;14898:26;:52;14925:24;14942:6;;14925:16;:24::i;:::-;-1:-1:-1;;;;;14898:52:22;;;;;;;;;;;;-1:-1:-1;14898:52:22;;:57;14894:123;;14978:28;;-1:-1:-1;;;14978:28:22;;;;;;;;;;;14894:123;15026:36;15043:10;15055:6;;15026:16;:36::i;:::-;15072:49;15082:10;15094:15;;15111:9;15072;:49::i;14293:209::-;24302:4;24341;-1:-1:-1;;;;;24341:4:22;8398:10;24325:21;8386:72;;8432:15;;-1:-1:-1;;;8432:15:22;;;;;;;;;;;8386:72;14410:52:::1;14423:9;14434:13;14449:5;14456;14410:12;:52::i;:::-;14472:23;14489:5;14472:16;:23::i;9630:206::-:0;2334:13:0;:11;:13::i;:::-;9708:21:22::1;::::0;-1:-1:-1;;;;;9708:26:22;;::::1;:21:::0;::::1;:26:::0;9704:91:::1;;9757:27;;-1:-1:-1::0;;;9757:27:22::1;;;;;;;;;;;9704:91;9804:21;:25:::0;;-1:-1:-1;;;;;;9804:25:22::1;-1:-1:-1::0;;;;;9804:25:22;;;::::1;::::0;;;::::1;::::0;;9630:206::o;21068:144::-;21169:23;;;;:16;:23;;;;;;;;;:36;;21162:43;;;;;;;;;;;;;;;;;21134:16;;21162:43;;;21169:36;21162:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21068:144;;;:::o;10426:372::-;10518:21;;-1:-1:-1;;;;;10518:21:22;10504:10;:35;10500:88;;10562:15;;-1:-1:-1;;;10562:15:22;;;;;;;;;;;10500:88;-1:-1:-1;;;;;10601:20:22;;;;;;;:14;:20;;;;;;:26;;;:20;;:26;10597:83;;10650:19;;-1:-1:-1;;;10650:19:22;;;;;;;;;;;10597:83;10701:2;-1:-1:-1;;;;;10693:10:22;:4;-1:-1:-1;;;;;10693:10:22;;10689:61;;10726:13;;-1:-1:-1;;;10726:13:22;;;;;;;;;;;10689:61;-1:-1:-1;;;;;10759:27:22;;;;;;;:21;:27;;;;;:32;;-1:-1:-1;;;;;;10759:32:22;;;;;;;;10426:372::o;45704:565::-;46382:4;46405:25;;;:12;:25;;;;;:37;;;45783:88;;45840:20;;-1:-1:-1;;;45840:20:22;;;;;;;;;;;45783:88;45917:14;45934:25;;;:12;:25;;;;;:39;;;;45987:32;;:45;45983:86;;-1:-1:-1;46057:1:22;45983:86;46078:4;;:47;;-1:-1:-1;;;46078:47:22;;;;;15042:25:27;;;15083:18;;;15076:34;;;-1:-1:-1;;;;;46078:4:22;;;;:26;;15015:18:27;;46078:47:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46139:10;:25;;;;-1:-1:-1;46153:11:22;;;46139:25;46135:128;;;46180:4;;;46220:31;;;:18;:31;;;;;;;;;46180:72;;-1:-1:-1;;;46180:72:22;;-1:-1:-1;;;;;46180:4:22;;;;:26;;:72;;46207:11;;46220:31;46180:72;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45773:496;45704:565;;:::o;10937:340::-;11001:10;-1:-1:-1;;;;;11025:16:22;;11021:67;;11064:13;;-1:-1:-1;;;11064:13:22;;;;;;;;;;;11021:67;-1:-1:-1;;;;;11101:27:22;;;;;;;:21;:27;;;;;;;;:33;;;;11097:89;;11157:18;;-1:-1:-1;;;11157:18:22;;;;;;;;;;;11097:89;-1:-1:-1;;;;;11195:20:22;;;;;;;:14;:20;;;;;;;;:25;;;;;;-1:-1:-1;;;;;;11195:25:22;;;;;;;11230:21;:27;;;;;;:40;;;;;;;10937:340::o;12894:603::-;24302:4;24341;-1:-1:-1;;;;;24341:4:22;8398:10;24325:21;8386:72;;8432:15;;-1:-1:-1;;;8432:15:22;;;;;;;;;;;8386:72;12990:30:::1;13023:16;:32;13040:14;:12;:14::i;:::-;13023:32;;;;;;;;;;;12990:65;;13113:9;13125:1;13113:13;;13108:333;13128:27:::0;;::::1;13108:333;;;13176:19;13198:16;;13215:1;13198:19;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;::::1;;13231:21;13255:25:::0;;;:12:::1;:25:::0;;;;;;:39:::1;;::::0;13308:35;;;;;;:51;;;13395:19:::1;::::0;::::1;::::0;13198;;-1:-1:-1;13395:35:22::1;::::0;-1:-1:-1;13255:39:22;;13395:35:::1;:::i;:::-;13373:19;::::0;::::1;:57:::0;-1:-1:-1;;13157:3:22::1;;13108:333;;;-1:-1:-1::0;13450:40:22::1;:21;::::0;::::1;13474:16:::0;;13450:40:::1;:::i;:::-;;12980:517;12894:603:::0;;:::o;18417:111::-;2334:13:0;:11;:13::i;:::-;18495:22:22::1;:26:::0;;-1:-1:-1;;;;;;18495:26:22::1;-1:-1:-1::0;;;;;18495:26:22;;;::::1;::::0;;;::::1;::::0;;18417:111::o;11579:1146::-;24302:4;24341;-1:-1:-1;;;;;24341:4:22;8398:10;24325:21;8386:72;;8432:15;;-1:-1:-1;;;8432:15:22;;;;;;;;;;;8386:72;11797:30:::1;11830:16;:32;11847:14;:12;:14::i;:::-;11830:32;;;;;;;;;;;11797:65;;11872:29;11904:8;:21;;11872:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11936:69;11954:8;11964:12;11978:11;;11936:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11991:13;;11936:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;11936:17:22::1;::::0;-1:-1:-1;;;11936:69:22:i:1;:::-;12083:18;::::0;;12029:34:::1;12066:36:::0;;;:16:::1;:36;::::0;;;;12168:20:::1;::::0;::::1;::::0;12066:36;;12083:18;46983:15;12159:29:::1;12155:113;;;12233:20;::::0;::::1;::::0;12224:29:::1;::::0;46983:15;12224:29:::1;:::i;:::-;12208:45;;12155:113;12281:97;12299:13;12314:8;12324:12;12338;12352:7;;12281:97;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12361:16;;12281:97;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;12281:17:22::1;::::0;-1:-1:-1;;;12281:97:22:i:1;:::-;12392:85;12416:13;12431:8;12441:12;12455;12469:7;;12392:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;12392:23:22::1;::::0;-1:-1:-1;;;12392:85:22:i:1;:::-;12015:473;;12519:14;:12;:14::i;:::-;12498:18;:35:::0;46983:15;12543:16:::1;::::0;::::1;:25:::0;12598:12:::1;12578:17;::::0;::::1;:32:::0;12651:1:::1;::::0;:23:::1;::::0;;-1:-1:-1;;;12651:23:22;;;;-1:-1:-1;;;;;12651:1:22;;::::1;::::0;:21:::1;::::0;:23:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;:1;:23:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12620:28;::::0;::::1;:54:::0;-1:-1:-1;12707:11:22::1;::::0;;12684:20;::::1;:34:::0;-1:-1:-1;;;;;;;;11579:1146:22:o;3405:215:0:-;2334:13;:11;:13::i;:::-;-1:-1:-1;;;;;3489:22:0;::::1;3485:91;;3534:31;::::0;-1:-1:-1;;;3534:31:0;;3562:1:::1;3534:31;::::0;::::1;961:51:27::0;934:18;;3534:31:0::1;;;;;;;;3485:91;3585:28;3604:8;3585:18;:28::i;31783:488:22:-:0;31866:7;31885:39;31899:9;31910:13;31885;:39::i;:::-;-1:-1:-1;;;;;;31952:24:22;;31934:15;31952:24;;;:13;:24;;;;;;;;:39;;;;;;;;;;32005:12;;;32001:63;;32040:13;;-1:-1:-1;;;32040:13:22;;;;;;;;;;;32001:63;-1:-1:-1;;;;;32080:24:22;;;;;;:13;:24;;;;;;;;:39;;;;;;;;32073:46;32215:25;32232:7;32215:16;:25::i;:::-;32257:7;31783:488;-1:-1:-1;;;31783:488:22:o;24398:490::-;46382:4;46405:25;;;:12;:25;;;;;:37;;;24494:90;;24553:20;;-1:-1:-1;;;24553:20:22;;;;;;;;;;;24494:90;788:1;24597:27;;;:12;:27;;;;;:34;:47;24593:105;;24667:20;;-1:-1:-1;;;24667:20:22;;;;;;;;;;;24593:105;24707:52;24720:9;24731:13;24746:6;24754:4;24707:12;:52::i;:::-;24774:40;24800:13;24774:25;:40::i;:::-;24769:113;;24837:34;;-1:-1:-1;;;24837:34:22;;;;;;;;;;;33032:265;-1:-1:-1;;;;;33130:20:22;;;33090:15;33130:20;;;:14;:20;;;;;;33090:15;;33130:20;;33160:85;;-1:-1:-1;33227:4:22;;33032:265;-1:-1:-1;33032:265:22:o;44703:961::-;788:1;44797:25;;;:12;:25;;;;;:32;:45;:68;;;;-1:-1:-1;44846:19:22;;;44797:68;44793:176;;;44919:25;;;;:12;:25;;;;;:39;;;44900:16;;:58;;44919:39;44900:58;:::i;:::-;44881:16;:77;44793:176;45049:25;;;;:12;:25;;;;;:32;45040:41;;45036:622;;;45097:25;;;;:12;:25;;;;;:41;;;45156:42;;;:47;;45152:434;;45268:14;:12;:14::i;:::-;45223:25;;;;:12;:25;;;;;;;;;:42;;;:59;;;46983:15;45300:41;;;;:50;;;45373:198;;15042:25:27;;;15083:18;;;15076:34;45373:198:22;;45223:25;;45373:198;;;;;;;;;45152:434;45627:11;45604:43;45640:6;45604:43;;;;548:25:27;;536:2;521:18;;402:177;43978:677:22;44088:22;;-1:-1:-1;;;;;44088:22:22;:36;44084:565;;44291:22;;44350:89;;-1:-1:-1;;;;;16544:32:27;;;44350:89:22;;;16526:51:27;16613:32;;;16593:18;;;16586:60;44273:12:22;;44291:22;;44324:7;;16499:18:27;;44350:89:22;;;-1:-1:-1;;44350:89:22;;;;;;;;;;;;;;-1:-1:-1;;;;;44350:89:22;-1:-1:-1;;;44350:89:22;;;44291:162;;;44350:89;44291:162;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44272:181;;;44557:7;44556:8;:18;;;;;44568:6;44556:18;44552:87;;;44601:23;;-1:-1:-1;;;44601:23:22;;;;;;;;;;;1847:127:0;6931:20:1;:18;:20::i;:::-;1929:38:0::1;1954:12;1929:24;:38::i;2970:67:2:-:0;6931:20:1;:18;:20::i;27805:1676:22:-;-1:-1:-1;;;;;27959:31:22;;27924:32;27959:31;;;:20;:31;;;;;;;;:46;;;;;;;;:52;;;;;;;;27924:87;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28025:18;28021:74;;28066:18;;-1:-1:-1;;;28066:18:22;;;;;;;;;;;28021:74;28127:12;;;;;28172:13;;28105:19;28212:27;;;:12;:27;;;;;;;:43;;;28127:12;;28172:13;28212:48;;;;:121;;-1:-1:-1;28276:27:22;;;;:12;:27;;;;;:43;;;:57;-1:-1:-1;28212:121:22;28195:304;;;-1:-1:-1;;28372:27:22;;;;:12;:27;;;;;:43;;;;28444:44;;;;;28195:304;28536:1;;;;;;;;;-1:-1:-1;;;;;28536:1:22;-1:-1:-1;;;;;28536:22:22;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;28522:38;;:11;:38;:::i;:::-;46983:15;28513:47;28509:106;;;28583:21;;-1:-1:-1;;;28583:21:22;;;;;;;;;;;28509:106;28661:1;;;;;;;;;-1:-1:-1;;;;;28661:1:22;-1:-1:-1;;;;;28661:24:22;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;28646:41;;:12;:41;:::i;:::-;28629:14;:12;:14::i;:::-;:58;28625:119;;;28710:23;;-1:-1:-1;;;28710:23:22;;;;;;;;;;;28625:119;-1:-1:-1;;;;;28771:31:22;;28754:14;28771:31;;;:20;:31;;;;;;;;:46;;;;;;;;:52;;;;;;;;:59;;;;;23405:25;;;;;;;;;:32;28947:19;:34;;;;;;;28771:59;;995:6;23405:47;;;:52;;;28754:14;28909:73;;28771:59;;23405:52;;28909:18;:73::i;:::-;-1:-1:-1;;;;;28999:31:22;;;;;;:20;:31;;;;;;;;:46;;;;;;;;:52;;;;;;;;28992:59;;;;;;;;;;;;28891:91;-1:-1:-1;29066:17:22;;;29062:76;;29106:21;;-1:-1:-1;;;29106:21:22;;;;;;;;;;;29062:76;29238:9;-1:-1:-1;;;;;29253:13:22;;29274:16;29283:7;29274:6;:16;:::i;:::-;29253:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29237:58;;;29310:4;29305:59;;29337:16;;-1:-1:-1;;;29337:16:22;;;;;;;;;;;29305:59;29373:17;29382:7;29373:8;:17::i;:::-;29442:4;29427:13;-1:-1:-1;;;;;29406:68:22;;;29448:16;29457:7;29448:6;:16;:::i;:::-;29406:68;;;15042:25:27;;;15098:2;15083:18;;15076:34;;;15015:18;29406:68:22;;;;;;;27914:1567;;;;;;;27805:1676;;;;:::o;4603:312:2:-;4683:4;-1:-1:-1;;;;;4692:6:2;4675:23;;;:120;;;4789:6;-1:-1:-1;;;;;4753:42:2;:32;-1:-1:-1;;;;;;;;;;;1519:53:7;-1:-1:-1;;;;;1519:53:7;;1441:138;4753:32:2;-1:-1:-1;;;;;4753:42:2;;;4675:120;4658:251;;;4869:29;;-1:-1:-1;;;4869:29:2;;;;;;;;;;;9367:66:22;2334:13:0;:11;:13::i;6057:538:2:-;6174:17;-1:-1:-1;;;;;6156:50:2;;:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6156:52:2;;;;;;;;-1:-1:-1;;6156:52:2;;;;;;;;;;;;:::i;:::-;;;6152:437;;6518:60;;-1:-1:-1;;;6518:60:2;;-1:-1:-1;;;;;979:32:27;;6518:60:2;;;961:51:27;934:18;;6518:60:2;815:203:27;6152:437:2;-1:-1:-1;;;;;;;;;;;6250:40:2;;6246:120;;6317:34;;-1:-1:-1;;;6317:34:2;;;;;548:25:27;;;521:18;;6317:34:2;402:177:27;6246:120:2;6379:54;6409:17;6428:4;6379:29;:54::i;2658:162:0:-;966:10:3;2717:7:0;1313:22;2570:8;-1:-1:-1;;;;;2570:8:0;;2441:144;2717:7;-1:-1:-1;;;;;2717:23:0;;2713:101;;2763:40;;-1:-1:-1;;;2763:40:0;;966:10:3;2763:40:0;;;961:51:27;934:18;;2763:40:0;815:203:27;31355:383:22;31438:12;31462:24;31489:37;31501:9;31512:13;31489:11;:37::i;:::-;31462:64;;31589:35;31610:13;31589:20;:35::i;:::-;-1:-1:-1;;;;;31536:35:22;;;;;;:24;:35;;;;;;;;:50;;;;;;;;:88;;;;31634:24;;;:13;:24;;;;;:39;;;;;;;;;:59;;31677:16;;31536:35;31634:59;;31677:16;;31634:59;:::i;:::-;;;;-1:-1:-1;;31710:21:22;;;31355:383;-1:-1:-1;;;31355:383:22:o;25854:1313::-;-1:-1:-1;;;;;26063:19:22;;;;;;:8;:19;;;;;;;;:34;;;;;;;;:44;;26101:6;;26063:19;:44;;26101:6;;26063:44;:::i;:::-;;;;-1:-1:-1;;26161:27:22;;;;:12;:27;;;;;:41;;;:50;;26205:6;;26161:50;:::i;:::-;26117:27;;;;:12;:27;;;;;:41;;:94;26234:10;;:19;;26247:6;;26234:19;:::i;:::-;26221:10;:32;788:1;26267:27;;;:12;:27;;;;;:34;26263:122;;26368:6;26349:16;;:25;;;;:::i;:::-;26330:16;:44;26263:122;26395:27;26425;26438:13;26425:12;:27::i;:::-;26395:57;-1:-1:-1;26466:24:22;;;;;:75;;-1:-1:-1;788:1:22;26494:27;;;:12;:27;;;;;:34;:47;26466:75;26462:613;;;26586:1;;;;;;;;;-1:-1:-1;;;;;26586:1:22;-1:-1:-1;;;;;26586:14:22;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;26563:19;:39;;26557:266;;26627:8;26623:186;;;26666:23;;-1:-1:-1;;;26666:23:22;;;;;;;;;;;26623:186;26736:54;26761:13;837:1;26736:24;:54::i;:::-;26840:19;:64;;;;;26864:40;26890:13;26864:25;:40::i;:::-;26863:41;26840:64;26836:144;;;26931:34;;-1:-1:-1;;;26931:34:22;;;;;;;;;;;26836:144;26462:613;;;27010:54;27035:13;837:1;27010:24;:54::i;:::-;27119:27;;;;:12;:27;;;;;;;;:32;;27085:75;;27108:9;;-1:-1:-1;;;;;27119:32:22;27153:6;27085:22;:75::i;5032:213:2:-;5106:4;-1:-1:-1;;;;;5115:6:2;5098:23;;5094:145;;5199:29;;-1:-1:-1;;;5199:29:2;;;;;;;;;;;30255:444:22;-1:-1:-1;;;;;30383:35:22;;30341:7;30383:35;;;:24;:35;;;;;;;;:50;;;;;;;;;30341:7;30466:35;30419:13;30466:20;:35::i;:::-;-1:-1:-1;;;;;30532:19:22;;30511:18;30532:19;;;:8;:19;;;;;;;;:34;;;;;;;;;30443:58;;-1:-1:-1;30597:68:22;30532:34;30552:13;30638:12;30443:58;30597:13;:68::i;:::-;30576:89;30255:444;-1:-1:-1;;;;;;;30255:444:22:o;3774:248:0:-;1313:22;3923:8;;-1:-1:-1;;;;;;3941:19:0;;-1:-1:-1;;;;;3941:19:0;;;;;;;;3975:40;;3923:8;;;;;3975:40;;3847:24;;3975:40;3837:185;;3774:248;:::o;41318:1215:22:-;-1:-1:-1;;;;;41608:20:22;;;;;;:14;:20;;;;;;:25;41604:80;;41656:17;;-1:-1:-1;;;41656:17:22;;;;;;;;;;;41604:80;-1:-1:-1;;;;;41693:20:22;;;;;;:14;:20;;;;;;;;:34;;;41737:25;;;:12;:25;;;;;;:41;;;41788:38;;;:53;;;41851:37;;;;:51;;;41912:41;;;:59;;;41981:42;;;:61;;;42052:30;;:37;;-1:-1:-1;;;;;;42052:37:22;;;;;;;42099:31;;:40;42133:6;;42099:31;:40;:::i;:::-;;42204:11;42149:26;:52;42176:24;42193:6;;42176:16;:24::i;:::-;-1:-1:-1;;;;;42149:52:22;-1:-1:-1;;;;;42149:52:22;;;;;;;;;;;;:66;;;;42261:4;-1:-1:-1;;;;;42231:62:22;42248:11;42231:62;42267:12;42281:11;42231:62;;;;;;15042:25:27;;;15098:2;15083:18;;15076:34;15030:2;15015:18;;14868:248;42231:62:22;;;;;;;;42307:21;;42303:125;;42349:68;;;15042:25:27;;;15098:2;15083:18;;15076:34;;;42370:11:22;;42349:68;;15015:18:27;42349:68:22;;;;;;;42303:125;42441:11;;42437:90;;42496:11;42473:43;42509:6;42473:43;;;;548:25:27;;536:2;521:18;;402:177;42473:43:22;;;;;;;;42437:90;41318:1215;;;;;;;;;:::o;32351:172::-;32408:11;;32404:113;;32435:36;;32451:1;;32435:36;;;;;32464:6;;32451:1;32435:36;32451:1;32435:36;32464:6;32451:1;32435:36;;;;;;;;;;;;;;;;;;;;-1:-1:-1;32490:16:22;;548:25:27;;;32490:16:22;;536:2:27;521:18;32490:16:22;;;;;;;32351:172;:::o;46726:152::-;46797:7;46857:10;:6;46864:1;46857:6;;:10;:::i;:::-;46847:21;;;;;;;:::i;:::-;;;;;;;;;;46726:152;-1:-1:-1;;;46726:152:22:o;41018:225::-;41100:19;41124:15;;41122:17;;;;;:::i;:::-;;;;;-1:-1:-1;41122:17:22;-1:-1:-1;41149:87:22;41169:4;41122:17;41188:6;;788:1;41207:14;:12;:14::i;:::-;46983:15;41231:1;41234;41149:19;:87::i;24967:837::-;25083:6;25093:1;25083:11;25079:61;;25117:12;;-1:-1:-1;;;25117:12:22;;;;;;;;;;;25079:61;25150:39;25164:9;25175:13;25150;:39::i;:::-;-1:-1:-1;;;;;;25237:19:22;;;;;;:8;:19;;;;;;;;:34;;;;;;;;;:43;;25274:6;;25237:43;:::i;:::-;-1:-1:-1;;;;;25200:19:22;;;;;;:8;:19;;;;;;;;:34;;;;;;;;:80;;;;25310:12;:27;;;:41;;;25405:18;25417:6;25310:41;25405:18;:::i;:::-;25361:27;;;;:12;:27;;;;;:41;;:62;25446:10;;:19;;25459:6;;25446:19;:::i;:::-;25433:10;:32;788:1;25479:27;;;:12;:27;;;;;:34;25475:122;;25580:6;25561:16;;:25;;;;:::i;:::-;25542:16;:44;25475:122;25607:45;25622:13;25637:14;;25607;:45::i;:::-;25689:13;25678:9;-1:-1:-1;;;;;25668:43:22;;25704:6;25668:43;;;;548:25:27;;536:2;521:18;;402:177;25668:43:22;;;;;;;;25756:27;;;;:12;:27;;;;;;;;:32;;25722:75;;25745:9;;-1:-1:-1;;;;;25756:32:22;25790:6;25722:22;:75::i;43621:222::-;43754:4;;:38;;-1:-1:-1;;;43754:38:22;;43778:4;43754:38;;;14442:51:27;14509:18;;;14502:34;;;-1:-1:-1;;;;;43754:4:22;;;;:15;;14415:18:27;;43754:38:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43830:6;43816:11;;:20;;;;:::i;:::-;43802:11;:34;-1:-1:-1;43621:222:22:o;33341:786::-;33585:9;33580:541;33604:12;:19;33600:1;:23;33580:541;;;33684:1;;;;;;;;;-1:-1:-1;;;;;33684:1:22;-1:-1:-1;;;;;33684:34:22;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;33665:13;33679:1;33665:16;;;;;;;;:::i;:::-;;;;;;;:55;:124;;;;;33758:1;;;;;;;;;-1:-1:-1;;;;;33758:1:22;-1:-1:-1;;;;;33758:29:22;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;33740:11;33752:1;33740:14;;;;;;;;:::i;:::-;;;;;;;:49;;33665:124;33644:303;;;33822:54;33847:12;33860:1;33847:15;;;;;;;;:::i;:::-;;;;;;;884:6;33822:24;:54::i;:::-;33894:38;33909:12;33922:1;33909:15;;;;;;;;:::i;:::-;;;;;;;33926:5;33894:14;:38::i;:::-;34024:11;34036:1;34024:14;;;;;;;;:::i;:::-;;;;;;;33984:8;:20;;:37;34005:12;34018:1;34005:15;;;;;;;;:::i;:::-;;;;;;;33984:37;;;;;;;;;;;:54;;;;34094:13;34108:1;34094:16;;;;;;;;:::i;:::-;;;;;;;34052:8;:22;;:39;34075:12;34088:1;34075:15;;;;;;;;:::i;:::-;;;;;;;;;;;;34052:39;;;;;;;;;;-1:-1:-1;34052:39:22;:58;33625:3;;33580:541;;34173:4421;34467:30;34500:170;;;;;;;;34547:12;:19;-1:-1:-1;;;;;34533:34:22;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;34533:34:22;;34500:170;;;;34581:1;34500:170;;;;34610:12;:19;-1:-1:-1;;;;;34596:34:22;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;34596:34:22;;34500:170;;;;34644:1;34500:170;;;;34659:1;34500:170;;;34467:203;;34686:9;34698:1;34686:13;;34681:830;34705:12;:19;34701:1;:23;34681:830;;;34745:29;34777:12;:40;;:57;34818:12;34831:1;34818:15;;;;;;;;:::i;:::-;;;;;;;34777:57;;;;;;;;;;;;34745:89;;34848:24;34875:1;34848:28;;34927:21;34894:27;34922:1;34894:30;;;;;;;;:::i;:::-;;;;;;;:54;34890:166;;;35020:21;34987:27;35015:1;34987:30;;;;;;;;:::i;:::-;;;;;;;:54;;;;:::i;:::-;34968:73;;34890:166;35339:13;35325:7;35333:1;35325:10;;;;;;;;:::i;:::-;;;;;;;35306:16;:29;;;;:::i;:::-;35305:47;;;;:::i;:::-;35280:3;:19;;;35300:1;35280:22;;;;;;;;:::i;:::-;;;;;;:72;;;;;35418:3;:19;;;35438:1;35418:22;;;;;;;;:::i;:::-;;;;;;;35392:3;:23;;;:48;;;;:::i;:::-;35366:23;;;:74;35469:12;;;;:31;;35484:16;;35469:31;:::i;:::-;35454:12;;;:46;-1:-1:-1;;34726:3:22;;34681:830;;;-1:-1:-1;35526:9:22;35521:388;35545:12;:19;35541:1;:23;35521:388;;;35791:13;35761:7;35769:1;35761:10;;;;;;;;:::i;:::-;;;;;;;35744:13;35730:7;35738:1;35730:10;;;;;;;;:::i;:::-;;;;;;;35688:8;:22;;:39;35711:12;35724:1;35711:15;;;;;;;;:::i;:::-;;;;;;;35688:39;;;;;;;;;;;;:52;;;;:::i;:::-;35687:70;;;;:::i;:::-;35686:85;;;;:::i;:::-;35685:119;;;;:::i;:::-;35642:21;;:24;;35664:1;;35642:24;;;;;;:::i;:::-;;;;;;;;;;:162;35874:21;;:24;;35896:1;;35874:24;;;;;;:::i;:::-;;;;;;;35846:3;:25;;;:52;;;;:::i;:::-;35818:25;;;:80;35566:3;;35521:388;;;-1:-1:-1;35924:9:22;35919:1807;35943:12;:19;35939:1;:23;35919:1807;;;35983:17;36003:203;36053:13;36084:1;;;;;;;;;-1:-1:-1;;;;;36084:1:22;-1:-1:-1;;;;;36084:21:22;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36125:21;;:24;;36147:1;;36125:24;;;;;;:::i;:::-;;;;;;;36167:3;:25;;;36003:32;:203::i;:::-;35983:223;;36276:93;36307:3;:12;;;36321:3;:19;;;36341:1;36321:22;;;;;;;;:::i;:::-;;;;;;;36345:3;:23;;;36276:30;:93::i;:::-;36248:121;;:9;:121;:::i;:::-;36220:149;;36384:19;36406:12;36419:1;36406:15;;;;;;;;:::i;:::-;;;;;;;;;;;;36435:21;36459:25;;;:12;:25;;;;;;;:30;;;;36619:1;;:23;;-1:-1:-1;;;36619:23:22;;;;36406:15;;-1:-1:-1;;;;;;36459:30:22;;;;36435:21;;36583:60;;36608:9;;36619:1;;;;;:21;;:23;;;;;;;;;;;:1;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36583:24;:60::i;:::-;-1:-1:-1;;;;;36677:23:22;;36657:17;36677:23;;;:8;:23;;;;;;;;:36;;;;;;;;;36552:91;;-1:-1:-1;36731:14:22;;36727:118;;-1:-1:-1;;;;;36765:28:22;;;;;;:13;:28;;;;;;;;:41;;;;;;;;:65;;36810:20;;36765:28;:65;;36810:20;;36765:65;:::i;:::-;;;;-1:-1:-1;;36727:118:22;36916:24;36943:32;36955:20;36943:9;:32;:::i;:::-;37101:21;37125:25;;;:12;:25;;;;;:39;;;36916:59;;-1:-1:-1;37222:18:22;;37218:125;;37315:13;37278:33;262:4:13;37278:16:22;:33;:::i;:::-;37277:51;;;;:::i;:::-;37260:68;;37218:125;37422:51;;;;:38;;;:51;;;;;;:84;;37492:14;;37422:84;:::i;:::-;37356:8;:34;;:47;37391:11;37356:47;;;;;;;;;;;:150;;;;37573:27;37601:1;37573:30;;;;;;;;:::i;:::-;;;;;;;37521:8;:36;;:49;37558:11;37521:49;;;;;;;;;;;:82;;;;37705:7;37713:1;37705:10;;;;;;;;:::i;:::-;;;;;;;37659:12;:30;;:43;37690:11;37659:43;;;;;;;;;;;;:56;;;;:::i;:::-;37617:8;:26;;:39;37644:11;37617:39;;;;;;;;;;;:98;;;;35969:1757;;;;;;;;35964:3;;;;;;;35919:1807;;;-1:-1:-1;37756:12:22;;;;37736:17;;;:32;;;37782:11;;:31;37778:140;;;37844:8;:17;;;37829:11;;:32;;;;;;;:::i;:::-;;;;-1:-1:-1;37778:140:22;;-1:-1:-1;37778:140:22;;37906:1;37892:11;:15;37778:140;37976:15;;-1:-1:-1;;;;;37976:15:22;:29;37972:616;;38021:16;262:4:13;38056:1:22;;;;;;;;;-1:-1:-1;;;;;38056:1:22;-1:-1:-1;;;;;38056:18:22;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38041:3;:12;;;:35;;;;:::i;:::-;38040:54;;;;:::i;:::-;38021:73;;38108:26;38125:8;38108:16;:26::i;:::-;38167:15;;:55;;38149:12;;-1:-1:-1;;;;;38167:15:22;;38210:7;;38195:8;;38149:12;38167:55;38149:12;38167:55;38195:8;38167:15;38210:7;38167:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38148:74;;;38298:7;38293:285;;38555:8;38529:22;;:34;;;;;;;:::i;:::-;;;;-1:-1:-1;;38007:581:22;;34457:4137;34173:4421;;;;;;:::o;38667:1314::-;38918:9;38913:1062;38937:12;:19;38933:1;:23;38913:1062;;;38977:19;38999:12;39012:1;38999:15;;;;;;;;:::i;:::-;;;;;;;38977:37;;39111:24;39170:13;39152:14;262:4:13;;197:76;39152:14:22;39139:7;39147:1;39139:10;;;;;;;;:::i;:::-;;;;;;;:27;;;;:::i;:::-;39138:45;;;;:::i;:::-;39111:72;-1:-1:-1;262:4:13;39201:16:22;:33;39197:105;;;-1:-1:-1;262:4:13;39197:105:22;39315:29;39347:39;;;:26;;;:39;;;;;;;;39315:71;;;;;;;;;-1:-1:-1;;;;;39315:71:22;;;;;-1:-1:-1;;;39315:71:22;;;;;;;;;;;-1:-1:-1;;;39315:71:22;;;;;;;;;;39431:64;39467:16;39315:71;39431:28;:64::i;:::-;39509:35;;;;:22;;;:35;;;;;;;;;:45;;;;;;;;;;;;-1:-1:-1;;;;;39509:45:22;;;-1:-1:-1;;39509:45:22;;;;;;;-1:-1:-1;;;39509:45:22;;;;;;-1:-1:-1;;;;39509:45:22;-1:-1:-1;;;39509:45:22;;;;;;;;39754:1;;:20;;-1:-1:-1;;;39754:20:22;;;;39509:45;;-1:-1:-1;;;;;;39754:1:22;;:18;;:20;;;;;39509:35;39754:20;;;;;;:1;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;39730:44:22;:7;:21;;;-1:-1:-1;;;;;39730:44:22;;:94;;;;;39796:1;;;;;;;;;-1:-1:-1;;;;;39796:1:22;-1:-1:-1;;;;;39796:26:22;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39778:46;;:7;:14;;;:46;;;;39730:94;39726:239;;;39844:54;39869:11;940:6;39844:24;:54::i;:::-;39916:34;39931:11;39944:5;39916:14;:34::i;:::-;-1:-1:-1;;38958:3:22;;;;;-1:-1:-1;38913:1062:22;;-1:-1:-1;38913:1062:22;;;38667:1314;;;;;:::o;23931:244::-;24010:4;262::13;24129:1:22;;;;;;;;;-1:-1:-1;;;;;24129:1:22;-1:-1:-1;;;;;24129:19:22;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;24101:25;24114:11;24101:12;:25::i;:::-;:49;;;;:::i;:::-;24100:68;;;;:::i;:::-;24045:25;;;;:12;:25;;;;;;:39;;;:123;;;;;;23931:244;-1:-1:-1;23931:244:22:o;7084:141:1:-;8870:21;8560:40;-1:-1:-1;;;8560:40:1;;;;7146:73;;7191:17;;-1:-1:-1;;;7191:17:1;;;;;;;;;;;1980:235:0;6931:20:1;:18;:20::i;27215:498:22:-;27349:15;27381:9;27380:10;:43;;;-1:-1:-1;262:4:13;27394:11:22;:29;;27380:43;27376:82;;;-1:-1:-1;27446:1:22;27439:8;;27376:82;262:4:13;27562:28:22;27579:11;262:4:13;27562:28:22;:::i;:::-;27552:39;;:6;:39;:::i;:::-;27551:58;;;;:::i;:::-;:62;;27612:1;27551:62;:::i;:::-;27541:72;;27637:6;27627:7;:16;27623:60;;;-1:-1:-1;27666:6:22;;27215:498;-1:-1:-1;;27215:498:22:o;2264:344:7:-;2355:37;2374:17;2355:18;:37::i;:::-;2407:36;;-1:-1:-1;;;;;2407:36:7;;;;;;;;2458:11;;:15;2454:148;;2489:53;2518:17;2537:4;2489:28;:53::i;2454:148::-;2573:18;:16;:18::i;29711:401:22:-;29785:7;29808:25;;;:12;:25;;;;;:42;;;:47;29804:267;;29896:25;;;;:12;:25;;;;;:42;;;29875:18;;:63;29871:127;;;-1:-1:-1;;29965:18:22;;;29711:401::o;29871:127::-;-1:-1:-1;30018:25:22;;;;:12;:25;;;;;:42;;;;29711:401::o;29804:267::-;-1:-1:-1;;30087:18:22;;;29711:401::o;30787:523::-;30951:7;30987;30974:9;:20;30970:59;;-1:-1:-1;31017:1:22;31010:8;;30970:59;31038:19;31060:27;;;:16;:27;;;;;;;;:68;;;:53;;;;:68;;;;;;31160:25;;;;;;;;;:66;;;:51;:66;;;;;;;262:4:13;31274:11:22;31245:25;31259:11;31245;:25;:::i;:::-;31244:41;;;;:::i;:::-;31243:60;;;;:::i;43149:439::-;43362:7;43385:16;43405:1;43385:21;43381:60;;-1:-1:-1;43429:1:22;43422:8;;43381:60;43450:19;43472:36;43488:20;43472:13;:36;:::i;:::-;43450:58;-1:-1:-1;43560:21:22;43526:30;43540:16;43450:58;43526:30;:::i;:::-;43525:56;;;;:::i;:::-;43518:63;43149:439;-1:-1:-1;;;;;;43149:439:22:o;42597:495::-;42761:7;42784:14;42802:1;42784:19;42780:58;;-1:-1:-1;42826:1:22;42819:8;;42780:58;42847:16;42896:19;42867:25;42878:14;42867:8;:25;:::i;:::-;42866:49;;;;:::i;:::-;42847:68;-1:-1:-1;262:4:13;43046:1:22;;;;;;;;;-1:-1:-1;;;;;43046:1:22;-1:-1:-1;;;;;43046:18:22;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;43026:1;;;;;;;;;-1:-1:-1;;;;;43026:1:22;-1:-1:-1;;;;;43026:15:22;;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;43009:34;;262:4:13;43009:34:22;:::i;:::-;:57;;;;:::i;:::-;42997:70;;:8;:70;:::i;:::-;42996:89;;;;:::i;:::-;42989:96;42597:495;-1:-1:-1;;;;;42597:495:22:o;46500:170::-;46596:7;262:4:13;46623:22:22;46635:10;46623:9;:22;:::i;:::-;46622:41;;;;:::i;39987:993::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40183:4:22;:11;;;:16;;40198:1;40183:16;40179:163;;-1:-1:-1;;;;;40215:28:22;;;;40306:1;40293:10;;;:14;40215:3;-1:-1:-1;40321:10:22;;40179:163;40417:9;40429:4;:11;;;40443:1;40429:15;;;;:::i;:::-;40417:27;;;;40496:11;40570:4;:14;;;40510:74;;40558:8;-1:-1:-1;;;;;40550:17:22;40528:4;:18;;;-1:-1:-1;;;;;40520:27:22;40515:1;40511;:5;;;;:::i;:::-;40510:37;;;;:::i;:::-;:57;;;;:::i;:::-;:74;;;;:::i;:::-;40496:88;-1:-1:-1;40622:7:22;40628:1;40496:88;40622:7;:::i;:::-;-1:-1:-1;;;;;40595:35:22;;;40663:7;40669:1;40663:3;:7;:::i;:::-;40640:31;;:13;;;:31;262:4:13;40686:17:22;;-1:-1:-1;;;;;40686:34:22;;40682:107;;;262:4:13;40736:42:22;;40682:107;40816:1;;;;;;;;;-1:-1:-1;;;;;40816:1:22;-1:-1:-1;;;;;40816:26:22;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40802:42;;:4;:11;;;:42;;;40798:156;;;40873:11;;;;:15;;40887:1;40873:15;:::i;:::-;40860:28;;:10;;;:28;40798:156;;;40932:11;;;;;40919:24;;:10;;;:24;40798:156;-1:-1:-1;40970:3:22;;39987:993;-1:-1:-1;;;;39987:993:22:o;1671:281:7:-;1748:17;-1:-1:-1;;;;;1748:29:7;;1781:1;1748:34;1744:119;;1805:47;;-1:-1:-1;;;1805:47:7;;-1:-1:-1;;;;;979:32:27;;1805:47:7;;;961:51:27;934:18;;1805:47:7;815:203:27;1744:119:7;-1:-1:-1;;;;;;;;;;;1872:73:7;;-1:-1:-1;;;;;;1872:73:7;-1:-1:-1;;;;;1872:73:7;;;;;;;;;;1671:281::o;3900:253:9:-;3983:12;4008;4022:23;4049:6;-1:-1:-1;;;;;4049:19:9;4069:4;4049:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4007:67;;;;4091:55;4118:6;4126:7;4135:10;4091:26;:55::i;6113:122:7:-;6163:9;:13;6159:70;;6199:19;;-1:-1:-1;;;6199:19:7;;;;;;;;;;;4421:582:9;4565:12;4594:7;4589:408;;4617:19;4625:10;4617:7;:19::i;:::-;4589:408;;;4841:17;;:22;:49;;;;-1:-1:-1;;;;;;4867:18:9;;;:23;4841:49;4837:119;;;4917:24;;-1:-1:-1;;;4917:24:9;;-1:-1:-1;;;;;979:32:27;;4917:24:9;;;961:51:27;934:18;;4917:24:9;815:203:27;4837:119:9;-1:-1:-1;4976:10:9;4969:17;;5543:487;5674:17;;:21;5670:354;;5871:10;5865:17;5927:15;5914:10;5910:2;5906:19;5899:44;5670:354;5994:19;;-1:-1:-1;;;5994:19:9;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:131:27;-1:-1:-1;;;;;89:31:27;;79:42;;69:70;;135:1;132;125:12;150:247;209:6;262:2;250:9;241:7;237:23;233:32;230:52;;;278:1;275;268:12;230:52;317:9;304:23;336:31;361:5;336:31;:::i;584:226::-;643:6;696:2;684:9;675:7;671:23;667:32;664:52;;;712:1;709;702:12;664:52;-1:-1:-1;757:23:27;;584:226;-1:-1:-1;584:226:27:o;1023:346::-;1091:6;1099;1152:2;1140:9;1131:7;1127:23;1123:32;1120:52;;;1168:1;1165;1158:12;1120:52;-1:-1:-1;;1213:23:27;;;1333:2;1318:18;;;1305:32;;-1:-1:-1;1023:346:27:o;1374:487::-;1451:6;1459;1467;1520:2;1508:9;1499:7;1495:23;1491:32;1488:52;;;1536:1;1533;1526:12;1488:52;1575:9;1562:23;1594:31;1619:5;1594:31;:::i;:::-;1644:5;1722:2;1707:18;;1694:32;;-1:-1:-1;1825:2:27;1810:18;;;1797:32;;1374:487;-1:-1:-1;;;1374:487:27:o;2730:771::-;2825:6;2833;2841;2849;2857;2910:3;2898:9;2889:7;2885:23;2881:33;2878:53;;;2927:1;2924;2917:12;2878:53;2972:23;;;-1:-1:-1;3092:2:27;3077:18;;3064:32;;-1:-1:-1;3174:2:27;3159:18;;3146:32;3187:33;3146:32;3187:33;:::i;:::-;3239:7;-1:-1:-1;3298:2:27;3283:18;;3270:32;3311:33;3270:32;3311:33;:::i;:::-;3363:7;-1:-1:-1;3422:3:27;3407:19;;3394:33;3436;3394;3436;:::i;:::-;3488:7;3478:17;;;2730:771;;;;;;;;:::o;3506:127::-;3567:10;3562:3;3558:20;3555:1;3548:31;3598:4;3595:1;3588:15;3622:4;3619:1;3612:15;3638:1079;3715:6;3723;3776:2;3764:9;3755:7;3751:23;3747:32;3744:52;;;3792:1;3789;3782:12;3744:52;3831:9;3818:23;3850:31;3875:5;3850:31;:::i;:::-;3900:5;-1:-1:-1;3956:2:27;3941:18;;3928:32;-1:-1:-1;;;;;3972:30:27;;3969:50;;;4015:1;4012;4005:12;3969:50;4038:22;;4091:4;4083:13;;4079:27;-1:-1:-1;4069:55:27;;4120:1;4117;4110:12;4069:55;4160:2;4147:16;-1:-1:-1;;;;;4178:6:27;4175:30;4172:56;;;4208:18;;:::i;:::-;4257:2;4251:9;4349:2;4311:17;;-1:-1:-1;;4307:31:27;;;4340:2;4303:40;4299:54;4287:67;;-1:-1:-1;;;;;4369:34:27;;4405:22;;;4366:62;4363:88;;;4431:18;;:::i;:::-;4467:2;4460:22;4491;;;4532:15;;;4549:2;4528:24;4525:37;-1:-1:-1;4522:57:27;;;4575:1;4572;4565:12;4522:57;4631:6;4626:2;4622;4618:11;4613:2;4605:6;4601:15;4588:50;4684:1;4679:2;4670:6;4662;4658:19;4654:28;4647:39;4705:6;4695:16;;;;;3638:1079;;;;;:::o;4722:466::-;4799:6;4807;4815;4868:2;4856:9;4847:7;4843:23;4839:32;4836:52;;;4884:1;4881;4874:12;4836:52;-1:-1:-1;;4929:23:27;;;5049:2;5034:18;;5021:32;;-1:-1:-1;5152:2:27;5137:18;;;5124:32;;4722:466;-1:-1:-1;4722:466:27:o;5580:367::-;5648:6;5656;5709:2;5697:9;5688:7;5684:23;5680:32;5677:52;;;5725:1;5722;5715:12;5677:52;5764:9;5751:23;5783:31;5808:5;5783:31;:::i;:::-;5833:5;5911:2;5896:18;;;;5883:32;;-1:-1:-1;;;5580:367:27:o;5952:347::-;6003:8;6013:6;6067:3;6060:4;6052:6;6048:17;6044:27;6034:55;;6085:1;6082;6075:12;6034:55;-1:-1:-1;6108:20:27;;-1:-1:-1;;;;;6140:30:27;;6137:50;;;6183:1;6180;6173:12;6137:50;6220:4;6212:6;6208:17;6196:29;;6272:3;6265:4;6256:6;6248;6244:19;6240:30;6237:39;6234:59;;;6289:1;6286;6279:12;6234:59;5952:347;;;;;:::o;6304:785::-;6401:6;6409;6417;6425;6433;6486:3;6474:9;6465:7;6461:23;6457:33;6454:53;;;6503:1;6500;6493:12;6454:53;6542:9;6529:23;6561:31;6586:5;6561:31;:::i;:::-;6611:5;-1:-1:-1;6689:2:27;6674:18;;6661:32;;-1:-1:-1;6770:2:27;6755:18;;6742:32;-1:-1:-1;;;;;6786:30:27;;6783:50;;;6829:1;6826;6819:12;6783:50;6868:58;6918:7;6909:6;6898:9;6894:22;6868:58;:::i;:::-;6304:785;;;;-1:-1:-1;6945:8:27;7053:2;7038:18;7025:32;;6304:785;-1:-1:-1;;;;6304:785:27:o;7094:288::-;7135:3;7173:5;7167:12;7200:6;7195:3;7188:19;7256:6;7249:4;7242:5;7238:16;7231:4;7226:3;7222:14;7216:47;7308:1;7301:4;7292:6;7287:3;7283:16;7279:27;7272:38;7371:4;7364:2;7360:7;7355:2;7347:6;7343:15;7339:29;7334:3;7330:39;7326:50;7319:57;;;7094:288;;;;:::o;7387:217::-;7534:2;7523:9;7516:21;7497:4;7554:44;7594:2;7583:9;7579:18;7571:6;7554:44;:::i;7609:409::-;7679:6;7687;7740:2;7728:9;7719:7;7715:23;7711:32;7708:52;;;7756:1;7753;7746:12;7708:52;7796:9;7783:23;-1:-1:-1;;;;;7821:6:27;7818:30;7815:50;;;7861:1;7858;7851:12;7815:50;7900:58;7950:7;7941:6;7930:9;7926:22;7900:58;:::i;:::-;7977:8;;7874:84;;-1:-1:-1;7609:409:27;-1:-1:-1;;;;7609:409:27:o;9090:611::-;9280:2;9292:21;;;9362:13;;9265:18;;;9384:22;;;9232:4;;9463:15;;;9437:2;9422:18;;;9232:4;9506:169;9520:6;9517:1;9514:13;9506:169;;;9581:13;;9569:26;;9624:2;9650:15;;;;9615:12;;;;9542:1;9535:9;9506:169;;;-1:-1:-1;9692:3:27;;9090:611;-1:-1:-1;;;;;9090:611:27:o;9898:388::-;9966:6;9974;10027:2;10015:9;10006:7;10002:23;9998:32;9995:52;;;10043:1;10040;10033:12;9995:52;10082:9;10069:23;10101:31;10126:5;10101:31;:::i;:::-;10151:5;-1:-1:-1;10208:2:27;10193:18;;10180:32;10221:33;10180:32;10221:33;:::i;:::-;10273:7;10263:17;;;9898:388;;;;;:::o;10291:395::-;10356:6;10364;10417:2;10405:9;10396:7;10392:23;10388:32;10385:52;;;10433:1;10430;10423:12;10385:52;10478:23;;;-1:-1:-1;10577:2:27;10562:18;;10549:32;10619:15;;10612:23;10600:36;;10590:64;;10650:1;10647;10640:12;10691:367;10754:8;10764:6;10818:3;10811:4;10803:6;10799:17;10795:27;10785:55;;10836:1;10833;10826:12;10785:55;-1:-1:-1;10859:20:27;;-1:-1:-1;;;;;10891:30:27;;10888:50;;;10934:1;10931;10924:12;10888:50;10971:4;10963:6;10959:17;10947:29;;11031:3;11024:4;11014:6;11011:1;11007:14;10999:6;10995:27;10991:38;10988:47;10985:67;;;11048:1;11045;11038:12;11063:437;11149:6;11157;11210:2;11198:9;11189:7;11185:23;11181:32;11178:52;;;11226:1;11223;11216:12;11178:52;11266:9;11253:23;-1:-1:-1;;;;;11291:6:27;11288:30;11285:50;;;11331:1;11328;11321:12;11285:50;11370:70;11432:7;11423:6;11412:9;11408:22;11370:70;:::i;11505:1431::-;11699:6;11707;11715;11723;11731;11739;11747;11755;11808:3;11796:9;11787:7;11783:23;11779:33;11776:53;;;11825:1;11822;11815:12;11776:53;11865:9;11852:23;-1:-1:-1;;;;;11890:6:27;11887:30;11884:50;;;11930:1;11927;11920:12;11884:50;11969:70;12031:7;12022:6;12011:9;12007:22;11969:70;:::i;:::-;12058:8;;-1:-1:-1;11943:96:27;-1:-1:-1;;12146:2:27;12131:18;;12118:32;-1:-1:-1;;;;;12162:32:27;;12159:52;;;12207:1;12204;12197:12;12159:52;12246:72;12310:7;12299:8;12288:9;12284:24;12246:72;:::i;:::-;12337:8;;-1:-1:-1;12220:98:27;-1:-1:-1;;12425:2:27;12410:18;;12397:32;-1:-1:-1;;;;;12441:32:27;;12438:52;;;12486:1;12483;12476:12;12438:52;12525:72;12589:7;12578:8;12567:9;12563:24;12525:72;:::i;:::-;12616:8;;-1:-1:-1;12499:98:27;-1:-1:-1;;12704:2:27;12689:18;;12676:32;-1:-1:-1;;;;;12720:32:27;;12717:52;;;12765:1;12762;12755:12;12717:52;12804:72;12868:7;12857:8;12846:9;12842:24;12804:72;:::i;:::-;11505:1431;;;;-1:-1:-1;11505:1431:27;;-1:-1:-1;11505:1431:27;;;;;;12895:8;-1:-1:-1;;;11505:1431:27:o;13365:127::-;13426:10;13421:3;13417:20;13414:1;13407:31;13457:4;13454:1;13447:15;13481:4;13478:1;13471:15;13497:125;13562:9;;;13583:10;;;13580:36;;;13596:18;;:::i;13627:380::-;13706:1;13702:12;;;;13749;;;13770:61;;13824:4;13816:6;13812:17;13802:27;;13770:61;13877:2;13869:6;13866:14;13846:18;13843:38;13840:161;;13923:10;13918:3;13914:20;13911:1;13904:31;13958:4;13955:1;13948:15;13986:4;13983:1;13976:15;13840:161;;13627:380;;;:::o;14012:251::-;14082:6;14135:2;14123:9;14114:7;14110:23;14106:32;14103:52;;;14151:1;14148;14141:12;14103:52;14183:9;14177:16;14202:31;14227:5;14202:31;:::i;14547:184::-;14617:6;14670:2;14658:9;14649:7;14645:23;14641:32;14638:52;;;14686:1;14683;14676:12;14638:52;-1:-1:-1;14709:16:27;;14547:184;-1:-1:-1;14547:184:27:o;14736:127::-;14797:10;14792:3;14788:20;14785:1;14778:31;14828:4;14825:1;14818:15;14852:4;14849:1;14842:15;15246:968;15418:6;15407:9;15400:25;15461:2;15456;15445:9;15441:18;15434:30;15381:4;15484:1;15517:6;15511:13;15547:36;15573:9;15547:36;:::i;:::-;15619:6;15614:2;15603:9;15599:18;15592:34;15657:1;15646:9;15642:17;15673:1;15668:158;;;;15840:1;15835:353;;;;15635:553;;15668:158;15735:3;15731:8;15720:9;15716:24;15711:2;15700:9;15696:18;15689:52;15813:2;15801:6;15794:14;15787:22;15784:1;15780:30;15769:9;15765:46;15761:55;15754:62;;15668:158;;15835:353;15866:6;15863:1;15856:17;15914:2;15911:1;15901:16;15939:1;15953:179;15967:6;15964:1;15961:13;15953:179;;;16060:14;;16036:17;;;16055:2;16032:26;16025:50;16116:1;16103:15;;;;15989:2;15982:10;15953:179;;;16156:17;;16175:2;16152:26;;-1:-1:-1;;15635:553:27;-1:-1:-1;16205:3:27;;15246:968;-1:-1:-1;;;;;;15246:968:27:o;16219:128::-;16286:9;;;16307:11;;;16304:37;;;16321:18;;:::i;16657:301::-;16786:3;16824:6;16818:13;16870:6;16863:4;16855:6;16851:17;16846:3;16840:37;16932:1;16896:16;;16921:13;;;-1:-1:-1;16896:16:27;16657:301;-1:-1:-1;16657:301:27:o;17152:517::-;17253:2;17248:3;17245:11;17242:421;;;17289:5;17286:1;17279:16;17333:4;17330:1;17320:18;17403:2;17391:10;17387:19;17384:1;17380:27;17374:4;17370:38;17439:4;17427:10;17424:20;17421:47;;;-1:-1:-1;17462:4:27;17421:47;17517:2;17512:3;17508:12;17505:1;17501:20;17495:4;17491:31;17481:41;;17572:81;17590:2;17583:5;17580:13;17572:81;;;17649:1;17635:16;;17616:1;17605:13;17572:81;;17845:1194;-1:-1:-1;;;;;17962:3:27;17959:27;17956:53;;;17989:18;;:::i;:::-;18018:93;18107:3;18067:38;18099:4;18093:11;18067:38;:::i;:::-;18061:4;18018:93;:::i;:::-;18137:1;18162:2;18157:3;18154:11;18179:1;18174:607;;;;18825:1;18842:3;18839:93;;;-1:-1:-1;18898:19:27;;;18885:33;18839:93;-1:-1:-1;;17802:1:27;17798:11;;;17794:24;17790:29;17780:40;17826:1;17822:11;;;17777:57;18945:78;;18147:886;;18174:607;15193:1;15186:14;;;15230:4;15217:18;;-1:-1:-1;;18210:17:27;;;18324:229;18338:7;18335:1;18332:14;18324:229;;;18427:19;;;18414:33;18399:49;;18534:4;18519:20;;;;18487:1;18475:14;;;;18354:12;18324:229;;;18328:3;18581;18572:7;18569:16;18566:159;;;18705:1;18701:6;18695:3;18689;18686:1;18682:11;18678:21;18674:34;18670:39;18657:9;18652:3;18648:19;18635:33;18631:79;18623:6;18616:95;18566:159;;;18768:1;18762:3;18759:1;18755:11;18751:19;18745:4;18738:33;18147:886;;17845:1194;;;:::o;19044:331::-;19149:9;19160;19202:8;19190:10;19187:24;19184:44;;;19224:1;19221;19214:12;19184:44;19253:6;19243:8;19240:20;19237:40;;;19273:1;19270;19263:12;19237:40;-1:-1:-1;;19299:23:27;;;19344:25;;;;;-1:-1:-1;19044:331:27:o;19380:277::-;19569:6;19561;19556:3;19543:33;19525:3;19595:16;;19620:13;;;19595:16;19380:277;-1:-1:-1;19380:277:27:o;19662:135::-;19701:3;19722:17;;;19719:43;;19742:18;;:::i;:::-;-1:-1:-1;19789:1:27;19778:13;;19662:135::o;19802:168::-;19875:9;;;19906;;19923:15;;;19917:22;;19903:37;19893:71;;19944:18;;:::i;19975:127::-;20036:10;20031:3;20027:20;20024:1;20017:31;20067:4;20064:1;20057:15;20091:4;20088:1;20081:15;20107:120;20147:1;20173;20163:35;;20178:18;;:::i;:::-;-1:-1:-1;20212:9:27;;20107:120::o;20232:288::-;20301:6;20354:2;20342:9;20333:7;20329:23;20325:32;20322:52;;;20370:1;20367;20360:12;20322:52;20402:9;20396:16;-1:-1:-1;;;;;20445:5:27;20441:30;20434:5;20431:41;20421:69;;20486:1;20483;20476:12;20525:280;20594:6;20647:2;20635:9;20626:7;20622:23;20618:32;20615:52;;;20663:1;20660;20653:12;20615:52;20695:9;20689:16;20745:10;20738:5;20734:22;20727:5;20724:33;20714:61;;20771:1;20768;20761:12;20810:167;20905:10;20878:18;;;20898;;;20874:43;;20929:19;;20926:45;;;20951:18;;:::i;20982:243::-;-1:-1:-1;;;;;21097:42:27;;;21053;;;21049:91;;21152:44;;21149:70;;;21199:18;;:::i;21230:317::-;-1:-1:-1;;;;;21315:42:27;;;21359;;;21311:91;21422:52;;;;21493:24;;;21483:58;;21521:18;;:::i;:::-;21483:58;21230:317;;;;:::o;21552:240::-;-1:-1:-1;;;;;21621:42:27;;;21665;;;21617:91;;21720:43;;21717:69;;;21766:18;;:::i;21797:227::-;21837:1;-1:-1:-1;;;;;21868:1:27;21864:42;21925:3;21915:37;;21932:18;;:::i;:::-;22014:3;-1:-1:-1;;;;;21974:1:27;21970:42;21966:52;21961:57;;;21797:227;;;;:::o;22029:219::-;22061:1;-1:-1:-1;;;;;22092:1:27;22088:42;22149:3;22139:37;;22156:18;;:::i;:::-;22238:3;-1:-1:-1;;;;;22198:1:27;22194:42;22190:52;22185:57;;;22029:219;;;;:::o
Swarm Source
ipfs://66d19146273283f0e3b105875ee752668c5f6172f37ee249748d1d959cb70425
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.