ETH Price: $2,855.53 (-10.20%)
Gas: 13 Gwei

Contract

0xB97178870F39d4389210086E4BcaccACD715c71d
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Delegate201802232024-06-27 3:05:358 days ago1719457535IN
0xB9717887...CD715c71d
0 ETH0.000304435.94330995
Delegate201703892024-06-25 18:08:359 days ago1719338915IN
0xB9717887...CD715c71d
0 ETH0.00017946.58490324
Delegate201703772024-06-25 18:06:119 days ago1719338771IN
0xB9717887...CD715c71d
0 ETH0.000231686.78705043
Delegate201102802024-06-17 8:21:2317 days ago1718612483IN
0xB9717887...CD715c71d
0 ETH0.000164083.20341612
Delegate198164512024-05-07 6:38:4759 days ago1715063927IN
0xB9717887...CD715c71d
0 ETH0.000332476.49219868
Delegate198003712024-05-05 0:38:3561 days ago1714869515IN
0xB9717887...CD715c71d
0 ETH0.000872924.45260692
Delegate197891092024-05-03 10:51:5962 days ago1714733519IN
0xB9717887...CD715c71d
0 ETH0.001764429
Delegate197215752024-04-24 0:09:4772 days ago1713917387IN
0xB9717887...CD715c71d
0 ETH0.000410128.00660347
Delegate197147322024-04-23 1:12:3573 days ago1713834755IN
0xB9717887...CD715c71d
0 ETH0.001244885.81644878
Delegate196866202024-04-19 2:49:4777 days ago1713494987IN
0xB9717887...CD715c71d
0 ETH0.0011347122.15238605
Delegate196834742024-04-18 16:16:4777 days ago1713457007IN
0xB9717887...CD715c71d
0 ETH0.0030843615.73150024
Delegate196833422024-04-18 15:49:3577 days ago1713455375IN
0xB9717887...CD715c71d
0 ETH0.0030372616
Delegate196792152024-04-18 1:59:2378 days ago1713405563IN
0xB9717887...CD715c71d
0 ETH0.002395412.30018977
Delegate195934182024-04-06 1:30:1190 days ago1712367011IN
0xB9717887...CD715c71d
0 ETH0.0005122310
Delegate194856382024-03-21 21:14:47105 days ago1711055687IN
0xB9717887...CD715c71d
0 ETH0.001930337.68439569
Delegate194331722024-03-14 12:13:11112 days ago1710418391IN
0xB9717887...CD715c71d
0 ETH0.0022729544.37370929
Delegate194196832024-03-12 14:45:47114 days ago1710254747IN
0xB9717887...CD715c71d
0 ETH0.00378473.87308163
Delegate193682532024-03-05 10:05:35121 days ago1709633135IN
0xB9717887...CD715c71d
0 ETH0.0031707561.90098215
Delegate193676812024-03-05 8:10:35121 days ago1709626235IN
0xB9717887...CD715c71d
0 ETH0.0143114373
Delegate193561552024-03-03 17:33:23123 days ago1709487203IN
0xB9717887...CD715c71d
0 ETH0.0032496163.44057556
Delegate193401682024-03-01 11:56:35125 days ago1709294195IN
0xB9717887...CD715c71d
0 ETH0.0023211645.31492195
Delegate193374642024-03-01 2:52:47126 days ago1709261567IN
0xB9717887...CD715c71d
0 ETH0.0098031550
Delegate193244562024-02-28 7:10:35127 days ago1709104235IN
0xB9717887...CD715c71d
0 ETH0.0018492236.10148871
Delegate192885952024-02-23 6:46:35133 days ago1708670795IN
0xB9717887...CD715c71d
0 ETH0.0145453381
Delegate192687422024-02-20 11:52:59135 days ago1708429979IN
0xB9717887...CD715c71d
0 ETH0.0043539585
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Delegations

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-11-04
*/

// File: @openzeppelin/contracts/math/SafeMath.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

// File: contracts/SafeMath96.sol

pragma solidity 0.6.12;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath96 {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint96 a, uint256 b) internal pure returns (uint96) {
        require(uint256(uint96(b)) == b, "SafeMath: addition overflow");
        uint96 c = a + uint96(b);
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint96 a, uint256 b) internal pure returns (uint96) {
        require(uint256(uint96(b)) == b, "SafeMath: subtraction overflow");
        return sub(a, uint96(b), "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     *
     * _Available since v2.4.0._
     */
    function sub(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {
        require(b <= a, errorMessage);
        uint96 c = a - b;

        return c;
    }

}

// File: contracts/spec_interfaces/IElections.sol

pragma solidity 0.6.12;

/// @title Elections contract interface
interface IElections {
	
	// Election state change events
	event StakeChanged(address indexed addr, uint256 selfDelegatedStake, uint256 delegatedStake, uint256 effectiveStake);
	event GuardianStatusUpdated(address indexed guardian, bool readyToSync, bool readyForCommittee);

	// Vote out / Vote unready
	event GuardianVotedUnready(address indexed guardian);
	event VoteUnreadyCasted(address indexed voter, address indexed subject, uint256 expiration);
	event GuardianVotedOut(address indexed guardian);
	event VoteOutCasted(address indexed voter, address indexed subject);

	/*
	 * External functions
	 */

    /// Notifies that the guardian is ready to sync with other nodes
    /// @dev may be called with either the guardian address or the guardian's orbs address
    /// @dev ready to sync state is not managed in the contract that only emits an event
    /// @dev readyToSync clears the readyForCommittee state
	function readyToSync() external;

    /// Notifies that the guardian is ready to join the committee
    /// @dev may be called with either the guardian address or the guardian's orbs address
    /// @dev a qualified guardian calling readyForCommittee is added to the committee
	function readyForCommittee() external;

    /// Checks if a guardian is qualified to join the committee
    /// @dev when true, calling readyForCommittee() will result in adding the guardian to the committee
    /// @dev called periodically by guardians to check if they are qualified to join the committee
    /// @param guardian is the guardian to check
    /// @return canJoin indicating that the guardian can join the current committee
	function canJoinCommittee(address guardian) external view returns (bool);

    /// Returns an address effective stake
    /// The effective stake is derived from a guardian delegate stake and selfs stake  
    /// @return effectiveStake is the guardian's effective stake
	function getEffectiveStake(address guardian) external view returns (uint effectiveStake);

    /// Returns the current committee along with the guardians' Orbs address and IP
    /// @return committee is a list of the committee members' guardian addresses
    /// @return weights is a list of the committee members' weight (effective stake)
    /// @return orbsAddrs is a list of the committee members' orbs address
    /// @return certification is a list of bool indicating the committee members certification
    /// @return ips is a list of the committee members' ip
	function getCommittee() external view returns (address[] memory committee, uint256[] memory weights, address[] memory orbsAddrs, bool[] memory certification, bytes4[] memory ips);

	// Vote-unready

    /// Casts an unready vote on a subject guardian
    /// @dev Called by a guardian as part of the automatic vote-unready flow
    /// @dev The transaction may be sent from the guardian or orbs address.
    /// @param subject is the subject guardian to vote out
    /// @param voteExpiration is the expiration time of the vote unready to prevent counting of a vote that is already irrelevant.
	function voteUnready(address subject, uint voteExpiration) external;

    /// Returns the current vote unready vote for a voter and a subject pair
    /// @param voter is the voting guardian address
    /// @param subject is the subject guardian address
    /// @return valid indicates whether there is a valid vote
    /// @return expiration returns the votes expiration time
	function getVoteUnreadyVote(address voter, address subject) external view returns (bool valid, uint256 expiration);

    /// Returns the current vote-unready status of a subject guardian.
    /// @dev the committee and certification data is used to check the certified and committee threshold
    /// @param subject is the subject guardian address
    /// @return committee is a list of the current committee members
    /// @return weights is a list of the current committee members weight
    /// @return certification is a list of bool indicating the committee members certification
    /// @return votes is a list of bool indicating the members that votes the subject unready
    /// @return subjectInCommittee indicates that the subject is in the committee
    /// @return subjectInCertifiedCommittee indicates that the subject is in the certified committee
	function getVoteUnreadyStatus(address subject) external view returns (
		address[] memory committee,
		uint256[] memory weights,
		bool[] memory certification,
		bool[] memory votes,
		bool subjectInCommittee,
		bool subjectInCertifiedCommittee
	);

	// Vote-out

    /// Casts a voteOut vote by the sender to the given address
    /// @dev the transaction is sent from the guardian address
    /// @param subject is the subject guardian address
	function voteOut(address subject) external;

    /// Returns the subject address the addr has voted-out against
    /// @param voter is the voting guardian address
    /// @return subject is the subject the voter has voted out
	function getVoteOutVote(address voter) external view returns (address);

    /// Returns the governance voteOut status of a guardian.
    /// @dev A guardian is voted out if votedStake / totalDelegatedStake (in percent mille) > threshold
    /// @param subject is the subject guardian address
    /// @return votedOut indicates whether the subject was voted out
    /// @return votedStake is the total stake voting against the subject
    /// @return totalDelegatedStake is the total delegated stake
	function getVoteOutStatus(address subject) external view returns (bool votedOut, uint votedStake, uint totalDelegatedStake);

	/*
	 * Notification functions from other PoS contracts
	 */

    /// Notifies a delegated stake change event
    /// @dev Called by: delegation contract
    /// @param delegate is the delegate to update
    /// @param selfDelegatedStake is the delegate self stake (0 if not self-delegating)
    /// @param delegatedStake is the delegate delegated stake (0 if not self-delegating)
    /// @param totalDelegatedStake is the total delegated stake
	function delegatedStakeChange(address delegate, uint256 selfDelegatedStake, uint256 delegatedStake, uint256 totalDelegatedStake) external /* onlyDelegationsContract onlyWhenActive */;

    /// Notifies a new guardian was unregistered
    /// @dev Called by: guardian registration contract
    /// @dev when a guardian unregisters its status is updated to not ready to sync and is removed from the committee
    /// @param guardian is the address of the guardian that unregistered
	function guardianUnregistered(address guardian) external /* onlyGuardiansRegistrationContract */;

    /// Notifies on a guardian certification change
    /// @dev Called by: guardian registration contract
    /// @param guardian is the address of the guardian to update
    /// @param isCertified indicates whether the guardian is certified
	function guardianCertificationChanged(address guardian, bool isCertified) external /* onlyCertificationContract */;


	/*
     * Governance functions
	 */

	event VoteUnreadyTimeoutSecondsChanged(uint32 newValue, uint32 oldValue);
	event VoteOutPercentMilleThresholdChanged(uint32 newValue, uint32 oldValue);
	event VoteUnreadyPercentMilleThresholdChanged(uint32 newValue, uint32 oldValue);
	event MinSelfStakePercentMilleChanged(uint32 newValue, uint32 oldValue);

    /// Sets the minimum self stake requirement for the effective stake
    /// @dev governance function called only by the functional manager
    /// @param minSelfStakePercentMille is the minimum self stake in percent-mille (0-100,000) 
	function setMinSelfStakePercentMille(uint32 minSelfStakePercentMille) external /* onlyFunctionalManager */;

    /// Returns the minimum self-stake required for the effective stake
    /// @return minSelfStakePercentMille is the minimum self stake in percent-mille 
	function getMinSelfStakePercentMille() external view returns (uint32);

    /// Sets the vote-out threshold
    /// @dev governance function called only by the functional manager
    /// @param voteOutPercentMilleThreshold is the minimum threshold in percent-mille (0-100,000)
	function setVoteOutPercentMilleThreshold(uint32 voteOutPercentMilleThreshold) external /* onlyFunctionalManager */;

    /// Returns the vote-out threshold
    /// @return voteOutPercentMilleThreshold is the minimum threshold in percent-mille
	function getVoteOutPercentMilleThreshold() external view returns (uint32);

    /// Sets the vote-unready threshold
    /// @dev governance function called only by the functional manager
    /// @param voteUnreadyPercentMilleThreshold is the minimum threshold in percent-mille (0-100,000)
	function setVoteUnreadyPercentMilleThreshold(uint32 voteUnreadyPercentMilleThreshold) external /* onlyFunctionalManager */;

    /// Returns the vote-unready threshold
    /// @return voteUnreadyPercentMilleThreshold is the minimum threshold in percent-mille
	function getVoteUnreadyPercentMilleThreshold() external view returns (uint32);

    /// Returns the contract's settings 
    /// @return minSelfStakePercentMille is the minimum self stake in percent-mille
    /// @return voteUnreadyPercentMilleThreshold is the minimum threshold in percent-mille
    /// @return voteOutPercentMilleThreshold is the minimum threshold in percent-mille
	function getSettings() external view returns (
		uint32 minSelfStakePercentMille,
		uint32 voteUnreadyPercentMilleThreshold,
		uint32 voteOutPercentMilleThreshold
	);

    /// Initializes the ready for committee notification for the committee guardians
    /// @dev governance function called only by the initialization admin during migration 
    /// @dev identical behaviour as if each guardian sent readyForCommittee() 
    /// @param guardians a list of guardians addresses to update
	function initReadyForCommittee(address[] calldata guardians) external /* onlyInitializationAdmin */;

}

// File: contracts/spec_interfaces/IDelegations.sol

pragma solidity 0.6.12;

/// @title Delegations contract interface
interface IDelegations /* is IStakeChangeNotifier */ {

    // Delegation state change events
	event DelegatedStakeChanged(address indexed addr, uint256 selfDelegatedStake, uint256 delegatedStake, address indexed delegator, uint256 delegatorContributedStake);

    // Function calls
	event Delegated(address indexed from, address indexed to);

	/*
     * External functions
     */

    /// Delegate your stake
    /// @dev updates the election contract on the changes in the delegated stake
    /// @dev updates the rewards contract on the upcoming change in the delegator's delegation state
    /// @param to is the address to delegate to
	function delegate(address to) external /* onlyWhenActive */;

    /// Refresh the address stake for delegation power based on the staking contract
    /// @dev Disabled stake change update notifications from the staking contract may create mismatches
    /// @dev refreshStake re-syncs the stake data with the staking contract
    /// @param addr is the address to refresh its stake
	function refreshStake(address addr) external /* onlyWhenActive */;

    /// Refresh the addresses stake for delegation power based on the staking contract
    /// @dev Batched version of refreshStake
    /// @dev Disabled stake change update notifications from the staking contract may create mismatches
    /// @dev refreshStakeBatch re-syncs the stake data with the staking contract
    /// @param addrs is the list of addresses to refresh their stake
	function refreshStakeBatch(address[] calldata addrs) external /* onlyWhenActive */;

    /// Returns the delegate address of the given address
    /// @param addr is the address to query
    /// @return delegation is the address the addr delegated to
	function getDelegation(address addr) external view returns (address);

    /// Returns a delegator info
    /// @param addr is the address to query
    /// @return delegation is the address the addr delegated to
    /// @return delegatorStake is the stake of the delegator as reflected in the delegation contract
	function getDelegationInfo(address addr) external view returns (address delegation, uint256 delegatorStake);
	
    /// Returns the delegated stake of an addr 
    /// @dev an address that is not self delegating has a 0 delegated stake
    /// @param addr is the address to query
    /// @return delegatedStake is the address delegated stake
	function getDelegatedStake(address addr) external view returns (uint256);

    /// Returns the total delegated stake
    /// @dev delegatedStake - the total stake delegated to an address that is self delegating
    /// @dev the delegated stake of a non self-delegated address is 0
    /// @return totalDelegatedStake is the total delegatedStake of all the addresses
	function getTotalDelegatedStake() external view returns (uint256) ;

	/*
	 * Governance functions
	 */

	event DelegationsImported(address[] from, address indexed to);

	event DelegationInitialized(address indexed from, address indexed to);

    /// Imports delegations during initial migration
    /// @dev initialization function called only by the initializationManager
    /// @dev Does not update the Rewards or Election contracts
    /// @dev assumes deactivated Rewards
    /// @param from is a list of delegator addresses
    /// @param to is the address the delegators delegate to
	function importDelegations(address[] calldata from, address to) external /* onlyMigrationManager onlyDuringDelegationImport */;

    /// Initializes the delegation of an address during initial migration 
    /// @dev initialization function called only by the initializationManager
    /// @dev behaves identically to a delegate transaction sent by the delegator
    /// @param from is the delegator addresses
    /// @param to is the delegator delegates to
	function initDelegation(address from, address to) external /* onlyInitializationAdmin */;
}

// File: contracts/IStakeChangeNotifier.sol

pragma solidity 0.6.12;

/// @title An interface for notifying of stake change events (e.g., stake, unstake, partial unstake, restate, etc.).
interface IStakeChangeNotifier {
    /// @dev Notifies of stake change event.
    /// @param _stakeOwner address The address of the subject stake owner.
    /// @param _amount uint256 The difference in the total staked amount.
    /// @param _sign bool The sign of the added (true) or subtracted (false) amount.
    /// @param _updatedStake uint256 The updated total staked amount.
    function stakeChange(address _stakeOwner, uint256 _amount, bool _sign, uint256 _updatedStake) external;

    /// @dev Notifies of multiple stake change events.
    /// @param _stakeOwners address[] The addresses of subject stake owners.
    /// @param _amounts uint256[] The differences in total staked amounts.
    /// @param _signs bool[] The signs of the added (true) or subtracted (false) amounts.
    /// @param _updatedStakes uint256[] The updated total staked amounts.
    function stakeChangeBatch(address[] calldata _stakeOwners, uint256[] calldata _amounts, bool[] calldata _signs,
        uint256[] calldata _updatedStakes) external;

    /// @dev Notifies of stake migration event.
    /// @param _stakeOwner address The address of the subject stake owner.
    /// @param _amount uint256 The migrated amount.
    function stakeMigration(address _stakeOwner, uint256 _amount) external;
}

// File: contracts/spec_interfaces/IStakingContractHandler.sol

pragma solidity 0.6.12;

/// @title Staking contract handler contract interface in addition to IStakeChangeNotifier
interface IStakingContractHandler {
    event StakeChangeNotificationSkipped(address indexed stakeOwner);
    event StakeChangeBatchNotificationSkipped(address[] stakeOwners);
    event StakeMigrationNotificationSkipped(address indexed stakeOwner);

    /*
    * External functions
    */

    /// Returns the stake of the specified stake owner (excluding unstaked tokens).
    /// @param stakeOwner address The address to check.
    /// @return uint256 The total stake.
    function getStakeBalanceOf(address stakeOwner) external view returns (uint256);

    /// Returns the total amount staked tokens (excluding unstaked tokens).
    /// @return uint256 is the total staked tokens of all stake owners.
    function getTotalStakedTokens() external view returns (uint256);

    /*
    * Governance functions
    */

    event NotifyDelegationsChanged(bool notifyDelegations);

    /// Sets notifications to the delegation contract
    /// @dev staking while notifications are disabled may lead to a discrepancy in the delegation data  
    /// @dev governance function called only by the migration manager
    /// @param notifyDelegations is a bool indicating whether to notify the delegation contract
    function setNotifyDelegations(bool notifyDelegations) external; /* onlyMigrationManager */

    /// Returns the notifications to the delegation contract status
    /// @return notifyDelegations is a bool indicating whether notifications are enabled
    function getNotifyDelegations() external view returns (bool);
}

// File: contracts/spec_interfaces/IStakingRewards.sol

pragma solidity 0.6.12;

/// @title Staking rewards contract interface
interface IStakingRewards {

    event DelegatorStakingRewardsAssigned(address indexed delegator, uint256 amount, uint256 totalAwarded, address guardian, uint256 delegatorRewardsPerToken, uint256 delegatorRewardsPerTokenDelta);
    event GuardianStakingRewardsAssigned(address indexed guardian, uint256 amount, uint256 totalAwarded, uint256 delegatorRewardsPerToken, uint256 delegatorRewardsPerTokenDelta, uint256 stakingRewardsPerWeight, uint256 stakingRewardsPerWeightDelta);
    event StakingRewardsClaimed(address indexed addr, uint256 claimedDelegatorRewards, uint256 claimedGuardianRewards, uint256 totalClaimedDelegatorRewards, uint256 totalClaimedGuardianRewards);
    event StakingRewardsAllocated(uint256 allocatedRewards, uint256 stakingRewardsPerWeight);
    event GuardianDelegatorsStakingRewardsPercentMilleUpdated(address indexed guardian, uint256 delegatorsStakingRewardsPercentMille);

    /*
     * External functions
     */

    /// Returns the current reward balance of the given address.
    /// @dev calculates the up to date balances (differ from the state)
    /// @param addr is the address to query
    /// @return delegatorStakingRewardsBalance the rewards awarded to the guardian role
    /// @return guardianStakingRewardsBalance the rewards awarded to the guardian role
    function getStakingRewardsBalance(address addr) external view returns (uint256 delegatorStakingRewardsBalance, uint256 guardianStakingRewardsBalance);

    /// Claims the staking rewards balance of an addr, staking the rewards
    /// @dev Claimed rewards are staked in the staking contract using the distributeRewards interface
    /// @dev includes the rewards for both the delegator and guardian roles
    /// @dev calculates the up to date rewards prior to distribute them to the staking contract
    /// @param addr is the address to claim rewards for
    function claimStakingRewards(address addr) external;

    /// Returns the current global staking rewards state
    /// @dev calculated to the latest block, may differ from the state read
    /// @return stakingRewardsPerWeight is the potential reward per 1E18 (TOKEN_BASE) committee weight assigned to a guardian was in the committee from day zero
    /// @return unclaimedStakingRewards is the of tokens that were assigned to participants and not claimed yet
    function getStakingRewardsState() external view returns (
        uint96 stakingRewardsPerWeight,
        uint96 unclaimedStakingRewards
    );

    /// Returns the current guardian staking rewards state
    /// @dev calculated to the latest block, may differ from the state read
    /// @dev notice that the guardian rewards are the rewards for the guardian role as guardian and do not include delegation rewards
    /// @dev use getDelegatorStakingRewardsData to get the guardian's rewards as delegator
    /// @param guardian is the guardian to query
    /// @return balance is the staking rewards balance for the guardian role
    /// @return claimed is the staking rewards for the guardian role that were claimed
    /// @return delegatorRewardsPerToken is the potential reward per token (1E18 units) assigned to a guardian's delegator that delegated from day zero
    /// @return delegatorRewardsPerTokenDelta is the increment in delegatorRewardsPerToken since the last guardian update
    /// @return lastStakingRewardsPerWeight is the up to date stakingRewardsPerWeight used for the guardian state calculation
    /// @return stakingRewardsPerWeightDelta is the increment in stakingRewardsPerWeight since the last guardian update
    function getGuardianStakingRewardsData(address guardian) external view returns (
        uint256 balance,
        uint256 claimed,
        uint256 delegatorRewardsPerToken,
        uint256 delegatorRewardsPerTokenDelta,
        uint256 lastStakingRewardsPerWeight,
        uint256 stakingRewardsPerWeightDelta
    );

    /// Returns the current delegator staking rewards state
    /// @dev calculated to the latest block, may differ from the state read
    /// @param delegator is the delegator to query
    /// @return balance is the staking rewards balance for the delegator role
    /// @return claimed is the staking rewards for the delegator role that were claimed
    /// @return guardian is the guardian the delegator delegated to receiving a portion of the guardian staking rewards
    /// @return lastDelegatorRewardsPerToken is the up to date delegatorRewardsPerToken used for the delegator state calculation
    /// @return delegatorRewardsPerTokenDelta is the increment in delegatorRewardsPerToken since the last delegator update
    function getDelegatorStakingRewardsData(address delegator) external view returns (
        uint256 balance,
        uint256 claimed,
        address guardian,
        uint256 lastDelegatorRewardsPerToken,
        uint256 delegatorRewardsPerTokenDelta
    );

    /// Returns an estimation for the delegator and guardian staking rewards for a given duration
    /// @dev the returned value is an estimation, assuming no change in the PoS state
    /// @dev the period calculated for start from the current block time until the current time + duration.
    /// @param addr is the address to estimate rewards for
    /// @param duration is the duration to calculate for in seconds
    /// @return estimatedDelegatorStakingRewards is the estimated reward for the delegator role
    /// @return estimatedGuardianStakingRewards is the estimated reward for the guardian role
    function estimateFutureRewards(address addr, uint256 duration) external view returns (
        uint256 estimatedDelegatorStakingRewards,
        uint256 estimatedGuardianStakingRewards
    );

    /// Sets the guardian's delegators staking reward portion
    /// @dev by default uses the defaultDelegatorsStakingRewardsPercentMille
    /// @param delegatorRewardsPercentMille is the delegators portion in percent-mille (0 - maxDelegatorsStakingRewardsPercentMille)
    function setGuardianDelegatorsStakingRewardsPercentMille(uint32 delegatorRewardsPercentMille) external;

    /// Returns a guardian's delegators staking reward portion
    /// @dev If not explicitly set, returns the defaultDelegatorsStakingRewardsPercentMille
    /// @return delegatorRewardsRatioPercentMille is the delegators portion in percent-mille
    function getGuardianDelegatorsStakingRewardsPercentMille(address guardian) external view returns (uint256 delegatorRewardsRatioPercentMille);

    /// Returns the amount of ORBS tokens in the staking rewards wallet allocated to staking rewards
    /// @dev The staking wallet balance must always larger than the allocated value
    /// @return allocated is the amount of tokens allocated in the staking rewards wallet
    function getStakingRewardsWalletAllocatedTokens() external view returns (uint256 allocated);

    /// Returns the current annual staking reward rate
    /// @dev calculated based on the current total committee weight
    /// @return annualRate is the current staking reward rate in percent-mille
    function getCurrentStakingRewardsRatePercentMille() external view returns (uint256 annualRate);

    /// Notifies an expected change in the committee membership of the guardian
    /// @dev Called only by: the Committee contract
    /// @dev called upon expected change in the committee membership of the guardian
    /// @dev triggers update of the global rewards state and the guardian rewards state
    /// @dev updates the rewards state based on the committee state prior to the change
    /// @param guardian is the guardian who's committee membership is updated
    /// @param weight is the weight of the guardian prior to the change
    /// @param totalCommitteeWeight is the total committee weight prior to the change
    /// @param inCommittee indicates whether the guardian was in the committee prior to the change
    /// @param inCommitteeAfter indicates whether the guardian is in the committee after the change
    function committeeMembershipWillChange(address guardian, uint256 weight, uint256 totalCommitteeWeight, bool inCommittee, bool inCommitteeAfter) external /* onlyCommitteeContract */;

    /// Notifies an expected change in a delegator and his guardian delegation state
    /// @dev Called only by: the Delegation contract
    /// @dev called upon expected change in a delegator's delegation state
    /// @dev triggers update of the global rewards state, the guardian rewards state and the delegator rewards state
    /// @dev on delegation change, updates also the new guardian and the delegator's lastDelegatorRewardsPerToken accordingly
    /// @param guardian is the delegator's guardian prior to the change
    /// @param guardianDelegatedStake is the delegated stake of the delegator's guardian prior to the change
    /// @param delegator is the delegator about to change delegation state
    /// @param delegatorStake is the stake of the delegator
    /// @param nextGuardian is the delegator's guardian after to the change
    /// @param nextGuardianDelegatedStake is the delegated stake of the delegator's guardian after to the change
    function delegationWillChange(address guardian, uint256 guardianDelegatedStake, address delegator, uint256 delegatorStake, address nextGuardian, uint256 nextGuardianDelegatedStake) external /* onlyDelegationsContract */;

    /*
     * Governance functions
     */

    event AnnualStakingRewardsRateChanged(uint256 annualRateInPercentMille, uint256 annualCap);
    event DefaultDelegatorsStakingRewardsChanged(uint32 defaultDelegatorsStakingRewardsPercentMille);
    event MaxDelegatorsStakingRewardsChanged(uint32 maxDelegatorsStakingRewardsPercentMille);
    event RewardDistributionActivated(uint256 startTime);
    event RewardDistributionDeactivated();
    event StakingRewardsBalanceMigrated(address indexed addr, uint256 guardianStakingRewards, uint256 delegatorStakingRewards, address toRewardsContract);
    event StakingRewardsBalanceMigrationAccepted(address from, address indexed addr, uint256 guardianStakingRewards, uint256 delegatorStakingRewards);
    event EmergencyWithdrawal(address addr, address token);

    /// Activates staking rewards allocation
    /// @dev governance function called only by the initialization admin
    /// @dev On migrations, startTime should be set to the previous contract deactivation time
    /// @param startTime sets the last assignment time
    function activateRewardDistribution(uint startTime) external /* onlyInitializationAdmin */;

    /// Deactivates fees and bootstrap allocation
    /// @dev governance function called only by the migration manager
    /// @dev guardians updates remain active based on the current perMember value
    function deactivateRewardDistribution() external /* onlyMigrationManager */;
    
    /// Sets the default delegators staking reward portion
    /// @dev governance function called only by the functional manager
    /// @param defaultDelegatorsStakingRewardsPercentMille is the default delegators portion in percent-mille(0 - maxDelegatorsStakingRewardsPercentMille)
    function setDefaultDelegatorsStakingRewardsPercentMille(uint32 defaultDelegatorsStakingRewardsPercentMille) external /* onlyFunctionalManager */;

    /// Returns the default delegators staking reward portion
    /// @return defaultDelegatorsStakingRewardsPercentMille is the default delegators portion in percent-mille
    function getDefaultDelegatorsStakingRewardsPercentMille() external view returns (uint32);

    /// Sets the maximum delegators staking reward portion
    /// @dev governance function called only by the functional manager
    /// @param maxDelegatorsStakingRewardsPercentMille is the maximum delegators portion in percent-mille(0 - 100,000)
    function setMaxDelegatorsStakingRewardsPercentMille(uint32 maxDelegatorsStakingRewardsPercentMille) external /* onlyFunctionalManager */;

    /// Returns the default delegators staking reward portion
    /// @return maxDelegatorsStakingRewardsPercentMille is the maximum delegators portion in percent-mille
    function getMaxDelegatorsStakingRewardsPercentMille() external view returns (uint32);

    /// Sets the annual rate and cap for the staking reward
    /// @dev governance function called only by the functional manager
    /// @param annualRateInPercentMille is the annual rate in percent-mille
    /// @param annualCap is the annual staking rewards cap
    function setAnnualStakingRewardsRate(uint32 annualRateInPercentMille, uint96 annualCap) external /* onlyFunctionalManager */;

    /// Returns the annual staking reward rate
    /// @return annualStakingRewardsRatePercentMille is the annual rate in percent-mille
    function getAnnualStakingRewardsRatePercentMille() external view returns (uint32);

    /// Returns the annual staking rewards cap
    /// @return annualStakingRewardsCap is the annual rate in percent-mille
    function getAnnualStakingRewardsCap() external view returns (uint256);

    /// Checks if rewards allocation is active
    /// @return rewardAllocationActive is a bool that indicates that rewards allocation is active
    function isRewardAllocationActive() external view returns (bool);

    /// Returns the contract's settings
    /// @return annualStakingRewardsCap is the annual rate in percent-mille
    /// @return annualStakingRewardsRatePercentMille is the annual rate in percent-mille
    /// @return defaultDelegatorsStakingRewardsPercentMille is the default delegators portion in percent-mille
    /// @return maxDelegatorsStakingRewardsPercentMille is the maximum delegators portion in percent-mille
    /// @return rewardAllocationActive is a bool that indicates that rewards allocation is active
    function getSettings() external view returns (
        uint annualStakingRewardsCap,
        uint32 annualStakingRewardsRatePercentMille,
        uint32 defaultDelegatorsStakingRewardsPercentMille,
        uint32 maxDelegatorsStakingRewardsPercentMille,
        bool rewardAllocationActive
    );

    /// Migrates the staking rewards balance of the given addresses to a new staking rewards contract
    /// @dev The new rewards contract is determined according to the contracts registry
    /// @dev No impact of the calling contract if the currently configured contract in the registry
    /// @dev may be called also while the contract is locked
    /// @param addrs is the list of addresses to migrate
    function migrateRewardsBalance(address[] calldata addrs) external;

    /// Accepts addresses balance migration from a previous rewards contract
    /// @dev the function may be called by any caller that approves the amounts provided for transfer
    /// @param addrs is the list migrated addresses
    /// @param migratedGuardianStakingRewards is the list of received guardian rewards balance for each address
    /// @param migratedDelegatorStakingRewards is the list of received delegator rewards balance for each address
    /// @param totalAmount is the total amount of staking rewards migrated for all addresses in the list. Must match the sum of migratedGuardianStakingRewards and migratedDelegatorStakingRewards lists.
    function acceptRewardsBalanceMigration(address[] calldata addrs, uint256[] calldata migratedGuardianStakingRewards, uint256[] calldata migratedDelegatorStakingRewards, uint256 totalAmount) external;

    /// Performs emergency withdrawal of the contract balance
    /// @dev called with a token to withdraw, should be called twice with the fees and bootstrap tokens
    /// @dev governance function called only by the migration manager
    /// @param erc20 is the ERC20 token to withdraw
    function emergencyWithdraw(address erc20) external /* onlyMigrationManager */;
}

// File: contracts/spec_interfaces/IManagedContract.sol

pragma solidity 0.6.12;

/// @title managed contract interface, used by the contracts registry to notify the contract on updates
interface IManagedContract /* is ILockable, IContractRegistryAccessor, Initializable */ {

    /// Refreshes the address of the other contracts the contract interacts with
    /// @dev called by the registry contract upon an update of a contract in the registry
    function refreshContracts() external;

}

// File: contracts/spec_interfaces/IContractRegistry.sol

pragma solidity 0.6.12;

/// @title Contract registry contract interface
/// @dev The contract registry holds Orbs PoS contracts and managers lists
/// @dev The contract registry updates the managed contracts on changes in the contract list
/// @dev Governance functions restricted to managers access the registry to retrieve the manager address 
/// @dev The contract registry represents the source of truth for Orbs Ethereum contracts 
/// @dev By tracking the registry events or query before interaction, one can access the up to date contracts 
interface IContractRegistry {

	event ContractAddressUpdated(string contractName, address addr, bool managedContract);
	event ManagerChanged(string role, address newManager);
	event ContractRegistryUpdated(address newContractRegistry);

	/*
	* External functions
	*/

    /// Updates the contracts address and emits a corresponding event
    /// @dev governance function called only by the migrationManager or registryAdmin
    /// @param contractName is the contract name, used to identify it
    /// @param addr is the contract updated address
    /// @param managedContract indicates whether the contract is managed by the registry and notified on changes
	function setContract(string calldata contractName, address addr, bool managedContract) external /* onlyAdminOrMigrationManager */;

    /// Returns the current address of the given contracts
    /// @param contractName is the contract name, used to identify it
    /// @return addr is the contract updated address
	function getContract(string calldata contractName) external view returns (address);

    /// Returns the list of contract addresses managed by the registry
    /// @dev Managed contracts are updated on changes in the registry contracts addresses 
    /// @return addrs is the list of managed contracts
	function getManagedContracts() external view returns (address[] memory);

    /// Locks all the managed contracts 
    /// @dev governance function called only by the migrationManager or registryAdmin
    /// @dev When set all onlyWhenActive functions will revert
	function lockContracts() external /* onlyAdminOrMigrationManager */;

    /// Unlocks all the managed contracts 
    /// @dev governance function called only by the migrationManager or registryAdmin
	function unlockContracts() external /* onlyAdminOrMigrationManager */;
	
    /// Updates a manager address and emits a corresponding event
    /// @dev governance function called only by the registryAdmin
    /// @dev the managers list is a flexible list of role to the manager's address
    /// @param role is the managers' role name, for example "functionalManager"
    /// @param manager is the manager updated address
	function setManager(string calldata role, address manager) external /* onlyAdmin */;

    /// Returns the current address of the given manager
    /// @param role is the manager name, used to identify it
    /// @return addr is the manager updated address
	function getManager(string calldata role) external view returns (address);

    /// Sets a new contract registry to migrate to
    /// @dev governance function called only by the registryAdmin
    /// @dev updates the registry address record in all the managed contracts
    /// @dev by tracking the emitted ContractRegistryUpdated, tools can track the up to date contracts
    /// @param newRegistry is the new registry contract 
	function setNewContractRegistry(IContractRegistry newRegistry) external /* onlyAdmin */;

    /// Returns the previous contract registry address 
    /// @dev used when the setting the contract as a new registry to assure a valid registry
    /// @return previousContractRegistry is the previous contract registry
	function getPreviousContractRegistry() external view returns (address);
}

// File: contracts/spec_interfaces/IContractRegistryAccessor.sol

pragma solidity 0.6.12;


interface IContractRegistryAccessor {

    /// Sets the contract registry address
    /// @dev governance function called only by an admin
    /// @param newRegistry is the new registry contract 
    function setContractRegistry(IContractRegistry newRegistry) external /* onlyAdmin */;

    /// Returns the contract registry address
    /// @return contractRegistry is the contract registry address
    function getContractRegistry() external view returns (IContractRegistry contractRegistry);

    function setRegistryAdmin(address _registryAdmin) external /* onlyInitializationAdmin */;

}

// File: @openzeppelin/contracts/GSN/Context.sol

pragma solidity ^0.6.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN 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 payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

// File: contracts/WithClaimableRegistryManagement.sol

pragma solidity 0.6.12;


/**
 * @title Claimable
 * @dev Extension for the Ownable contract, where the ownership needs to be claimed.
 * This allows the new owner to accept the transfer.
 */
contract WithClaimableRegistryManagement is Context {
    address private _registryAdmin;
    address private _pendingRegistryAdmin;

    event RegistryManagementTransferred(address indexed previousRegistryAdmin, address indexed newRegistryAdmin);

    /**
     * @dev Initializes the contract setting the deployer as the initial registryRegistryAdmin.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _registryAdmin = msgSender;
        emit RegistryManagementTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current registryAdmin.
     */
    function registryAdmin() public view returns (address) {
        return _registryAdmin;
    }

    /**
     * @dev Throws if called by any account other than the registryAdmin.
     */
    modifier onlyRegistryAdmin() {
        require(isRegistryAdmin(), "WithClaimableRegistryManagement: caller is not the registryAdmin");
        _;
    }

    /**
     * @dev Returns true if the caller is the current registryAdmin.
     */
    function isRegistryAdmin() public view returns (bool) {
        return _msgSender() == _registryAdmin;
    }

    /**
     * @dev Leaves the contract without registryAdmin. It will not be possible to call
     * `onlyManager` functions anymore. Can only be called by the current registryAdmin.
     *
     * NOTE: Renouncing registryManagement will leave the contract without an registryAdmin,
     * thereby removing any functionality that is only available to the registryAdmin.
     */
    function renounceRegistryManagement() public onlyRegistryAdmin {
        emit RegistryManagementTransferred(_registryAdmin, address(0));
        _registryAdmin = address(0);
    }

    /**
     * @dev Transfers registryManagement of the contract to a new account (`newManager`).
     */
    function _transferRegistryManagement(address newRegistryAdmin) internal {
        require(newRegistryAdmin != address(0), "RegistryAdmin: new registryAdmin is the zero address");
        emit RegistryManagementTransferred(_registryAdmin, newRegistryAdmin);
        _registryAdmin = newRegistryAdmin;
    }

    /**
     * @dev Modifier throws if called by any account other than the pendingManager.
     */
    modifier onlyPendingRegistryAdmin() {
        require(msg.sender == _pendingRegistryAdmin, "Caller is not the pending registryAdmin");
        _;
    }
    /**
     * @dev Allows the current registryAdmin to set the pendingManager address.
     * @param newRegistryAdmin The address to transfer registryManagement to.
     */
    function transferRegistryManagement(address newRegistryAdmin) public onlyRegistryAdmin {
        _pendingRegistryAdmin = newRegistryAdmin;
    }

    /**
     * @dev Allows the _pendingRegistryAdmin address to finalize the transfer.
     */
    function claimRegistryManagement() external onlyPendingRegistryAdmin {
        _transferRegistryManagement(_pendingRegistryAdmin);
        _pendingRegistryAdmin = address(0);
    }

    /**
     * @dev Returns the current pendingRegistryAdmin
    */
    function pendingRegistryAdmin() public view returns (address) {
       return _pendingRegistryAdmin;  
    }
}

// File: contracts/Initializable.sol

pragma solidity 0.6.12;

contract Initializable {

    address private _initializationAdmin;

    event InitializationComplete();

    /// Constructor
    /// Sets the initializationAdmin to the contract deployer
    /// The initialization admin may call any manager only function until initializationComplete
    constructor() public{
        _initializationAdmin = msg.sender;
    }

    modifier onlyInitializationAdmin() {
        require(msg.sender == initializationAdmin(), "sender is not the initialization admin");

        _;
    }

    /*
    * External functions
    */

    /// Returns the initializationAdmin address
    function initializationAdmin() public view returns (address) {
        return _initializationAdmin;
    }

    /// Finalizes the initialization and revokes the initializationAdmin role 
    function initializationComplete() external onlyInitializationAdmin {
        _initializationAdmin = address(0);
        emit InitializationComplete();
    }

    /// Checks if the initialization was completed
    function isInitializationComplete() public view returns (bool) {
        return _initializationAdmin == address(0);
    }

}

// File: contracts/ContractRegistryAccessor.sol

pragma solidity 0.6.12;





contract ContractRegistryAccessor is IContractRegistryAccessor, WithClaimableRegistryManagement, Initializable {

    IContractRegistry private contractRegistry;

    /// Constructor
    /// @param _contractRegistry is the contract registry address
    /// @param _registryAdmin is the registry admin address
    constructor(IContractRegistry _contractRegistry, address _registryAdmin) public {
        require(address(_contractRegistry) != address(0), "_contractRegistry cannot be 0");
        setContractRegistry(_contractRegistry);
        _transferRegistryManagement(_registryAdmin);
    }

    modifier onlyAdmin {
        require(isAdmin(), "sender is not an admin (registryManger or initializationAdmin)");

        _;
    }

    modifier onlyMigrationManager {
        require(isMigrationManager(), "sender is not the migration manager");

        _;
    }

    modifier onlyFunctionalManager {
        require(isFunctionalManager(), "sender is not the functional manager");

        _;
    }

    /// Checks whether the caller is Admin: either the contract registry, the registry admin, or the initialization admin
    function isAdmin() internal view returns (bool) {
        return msg.sender == address(contractRegistry) || msg.sender == registryAdmin() || msg.sender == initializationAdmin();
    }

    /// Checks whether the caller is a specific manager role or and Admin
    /// @dev queries the registry contract for the up to date manager assignment
    function isManager(string memory role) internal view returns (bool) {
        IContractRegistry _contractRegistry = contractRegistry;
        return isAdmin() || _contractRegistry != IContractRegistry(0) && contractRegistry.getManager(role) == msg.sender;
    }

    /// Checks whether the caller is the migration manager
    function isMigrationManager() internal view returns (bool) {
        return isManager('migrationManager');
    }

    /// Checks whether the caller is the functional manager
    function isFunctionalManager() internal view returns (bool) {
        return isManager('functionalManager');
    }

    /* 
     * Contract getters, return the address of a contract by calling the contract registry 
     */ 

    function getProtocolContract() internal view returns (address) {
        return contractRegistry.getContract("protocol");
    }

    function getStakingRewardsContract() internal view returns (address) {
        return contractRegistry.getContract("stakingRewards");
    }

    function getFeesAndBootstrapRewardsContract() internal view returns (address) {
        return contractRegistry.getContract("feesAndBootstrapRewards");
    }

    function getCommitteeContract() internal view returns (address) {
        return contractRegistry.getContract("committee");
    }

    function getElectionsContract() internal view returns (address) {
        return contractRegistry.getContract("elections");
    }

    function getDelegationsContract() internal view returns (address) {
        return contractRegistry.getContract("delegations");
    }

    function getGuardiansRegistrationContract() internal view returns (address) {
        return contractRegistry.getContract("guardiansRegistration");
    }

    function getCertificationContract() internal view returns (address) {
        return contractRegistry.getContract("certification");
    }

    function getStakingContract() internal view returns (address) {
        return contractRegistry.getContract("staking");
    }

    function getSubscriptionsContract() internal view returns (address) {
        return contractRegistry.getContract("subscriptions");
    }

    function getStakingRewardsWallet() internal view returns (address) {
        return contractRegistry.getContract("stakingRewardsWallet");
    }

    function getBootstrapRewardsWallet() internal view returns (address) {
        return contractRegistry.getContract("bootstrapRewardsWallet");
    }

    function getGeneralFeesWallet() internal view returns (address) {
        return contractRegistry.getContract("generalFeesWallet");
    }

    function getCertifiedFeesWallet() internal view returns (address) {
        return contractRegistry.getContract("certifiedFeesWallet");
    }

    function getStakingContractHandler() internal view returns (address) {
        return contractRegistry.getContract("stakingContractHandler");
    }

    /*
    * Governance functions
    */

    event ContractRegistryAddressUpdated(address addr);

    /// Sets the contract registry address
    /// @dev governance function called only by an admin
    /// @param newContractRegistry is the new registry contract 
    function setContractRegistry(IContractRegistry newContractRegistry) public override onlyAdmin {
        require(newContractRegistry.getPreviousContractRegistry() == address(contractRegistry), "new contract registry must provide the previous contract registry");
        contractRegistry = newContractRegistry;
        emit ContractRegistryAddressUpdated(address(newContractRegistry));
    }

    /// Returns the contract registry that the contract is set to use
    /// @return contractRegistry is the registry contract address
    function getContractRegistry() public override view returns (IContractRegistry) {
        return contractRegistry;
    }

    function setRegistryAdmin(address _registryAdmin) external override onlyInitializationAdmin {
        _transferRegistryManagement(_registryAdmin);
    }

}

// File: contracts/spec_interfaces/ILockable.sol

pragma solidity 0.6.12;

/// @title lockable contract interface, allows to lock a contract
interface ILockable {

    event Locked();
    event Unlocked();

    /// Locks the contract to external non-governance function calls
    /// @dev governance function called only by the migration manager or an admin
    /// @dev typically called by the registry contract upon locking all managed contracts
    /// @dev getters and migration functions remain active also for locked contracts
    /// @dev checked by the onlyWhenActive modifier
    function lock() external /* onlyMigrationManager */;

    /// Unlocks the contract 
    /// @dev governance function called only by the migration manager or an admin
    /// @dev typically called by the registry contract upon unlocking all managed contracts
    function unlock() external /* onlyMigrationManager */;

    /// Returns the contract locking status
    /// @return isLocked is a bool indicating the contract is locked 
    function isLocked() view external returns (bool);

}

// File: contracts/Lockable.sol

pragma solidity 0.6.12;



/// @title lockable contract
contract Lockable is ILockable, ContractRegistryAccessor {

    bool public locked;

    /// Constructor
    /// @param _contractRegistry is the contract registry address
    /// @param _registryAdmin is the registry admin address
    constructor(IContractRegistry _contractRegistry, address _registryAdmin) ContractRegistryAccessor(_contractRegistry, _registryAdmin) public {}

    /// Locks the contract to external non-governance function calls
    /// @dev governance function called only by the migration manager or an admin
    /// @dev typically called by the registry contract upon locking all managed contracts
    /// @dev getters and migration functions remain active also for locked contracts
    /// @dev checked by the onlyWhenActive modifier
    function lock() external override onlyMigrationManager {
        locked = true;
        emit Locked();
    }

    /// Unlocks the contract 
    /// @dev governance function called only by the migration manager or an admin
    /// @dev typically called by the registry contract upon unlocking all managed contracts
    function unlock() external override onlyMigrationManager {
        locked = false;
        emit Unlocked();
    }

    /// Returns the contract locking status
    /// @return isLocked is a bool indicating the contract is locked 
    function isLocked() external override view returns (bool) {
        return locked;
    }

    modifier onlyWhenActive() {
        require(!locked, "contract is locked for this operation");

        _;
    }
}

// File: contracts/ManagedContract.sol

pragma solidity 0.6.12;



/// @title managed contract
contract ManagedContract is IManagedContract, Lockable {

    /// @param _contractRegistry is the contract registry address
    /// @param _registryAdmin is the registry admin address
    constructor(IContractRegistry _contractRegistry, address _registryAdmin) Lockable(_contractRegistry, _registryAdmin) public {}

    /// Refreshes the address of the other contracts the contract interacts with
    /// @dev called by the registry contract upon an update of a contract in the registry
    function refreshContracts() virtual override external {}

}

// File: contracts/Delegations.sol

pragma solidity 0.6.12;









/// @title Delegations contract
contract Delegations is IDelegations, IStakeChangeNotifier, ManagedContract {
	using SafeMath for uint256;
	using SafeMath96 for uint96;

	address constant public VOID_ADDR = address(-1);

	struct StakeOwnerData {
		address delegation;
		uint96 stake;
	}
	mapping(address => StakeOwnerData) public stakeOwnersData;
	mapping(address => uint256) public uncappedDelegatedStake;

	uint256 totalDelegatedStake;

	struct DelegateStatus {
		address addr;
		uint256 uncappedDelegatedStake;
		bool isSelfDelegating;
		uint256 delegatedStake;
		uint96 selfDelegatedStake;
	}

    /// Constructor
    /// @param _contractRegistry is the contract registry address
    /// @param _registryAdmin is the registry admin address
	constructor(IContractRegistry _contractRegistry, address _registryAdmin) ManagedContract(_contractRegistry, _registryAdmin) public {
		address VOID_ADDRESS_DUMMY_DELEGATION = address(-2);
		assert(VOID_ADDR != VOID_ADDRESS_DUMMY_DELEGATION && VOID_ADDR != address(0) && VOID_ADDRESS_DUMMY_DELEGATION != address(0));
		stakeOwnersData[VOID_ADDR].delegation = VOID_ADDRESS_DUMMY_DELEGATION;
	}

	modifier onlyStakingContractHandler() {
		require(msg.sender == address(stakingContractHandler), "caller is not the staking contract handler");

		_;
	}

	/*
	* External functions
	*/

    /// Delegate your stake
    /// @dev updates the election contract on the changes in the delegated stake
    /// @dev updates the rewards contract on the upcoming change in the delegator's delegation state
    /// @param to is the address to delegate to
	function delegate(address to) external override onlyWhenActive {
		delegateFrom(msg.sender, to);
	}

    /// Refresh the address stake for delegation power based on the staking contract
    /// @dev Disabled stake change update notifications from the staking contract may create mismatches
    /// @dev refreshStake re-syncs the stake data with the staking contract
    /// @param addr is the address to refresh its stake
	function refreshStake(address addr) external override onlyWhenActive {
		_stakeChange(addr, stakingContractHandler.getStakeBalanceOf(addr));
	}

    /// Refresh the addresses stake for delegation power based on the staking contract
    /// @dev Batched version of refreshStake
    /// @dev Disabled stake change update notifications from the staking contract may create mismatches
    /// @dev refreshStakeBatch re-syncs the stake data with the staking contract
    /// @param addrs is the list of addresses to refresh their stake
	function refreshStakeBatch(address[] calldata addrs) external override onlyWhenActive {
		for (uint i = 0; i < addrs.length; i++) {
			_stakeChange(addrs[i], stakingContractHandler.getStakeBalanceOf(addrs[i]));
		}
	}

    /// Returns the delegate address of the given address
    /// @param addr is the address to query
    /// @return delegation is the address the addr delegated to
	function getDelegation(address addr) external override view returns (address) {
		return getStakeOwnerData(addr).delegation;
	}

    /// Returns a delegator info
    /// @param addr is the address to query
    /// @return delegation is the address the addr delegated to
    /// @return delegatorStake is the stake of the delegator as reflected in the delegation contract
	function getDelegationInfo(address addr) external override view returns (address delegation, uint256 delegatorStake) {
		StakeOwnerData memory data = getStakeOwnerData(addr);
		return (data.delegation, data.stake);
	}

    /// Returns the delegated stake of an addr 
    /// @dev an address that is not self delegating has a 0 delegated stake
    /// @param addr is the address to query
    /// @return delegatedStake is the address delegated stake
	function getDelegatedStake(address addr) external override view returns (uint256) {
		return getDelegateStatus(addr).delegatedStake;
	}

    /// Returns the total delegated stake
    /// @dev delegatedStake - the total stake delegated to an address that is self delegating
    /// @dev the delegated stake of a non self-delegated address is 0
    /// @return totalDelegatedStake is the total delegatedStake of all the addresses
	function getTotalDelegatedStake() external override view returns (uint256) {
		return totalDelegatedStake;
	}

	/*
	* Notifications from staking contract (IStakeChangeNotifier)
	*/

    /// Notifies of stake change event.
    /// @param _stakeOwner is the address of the subject stake owner.
    /// @param _updatedStake is the updated total staked amount.
	function stakeChange(address _stakeOwner, uint256, bool, uint256 _updatedStake) external override onlyStakingContractHandler onlyWhenActive {
		_stakeChange(_stakeOwner, _updatedStake);
	}

    /// Notifies of multiple stake change events.
    /// @param _stakeOwners is the addresses of subject stake owners.
    /// @param _amounts is the differences in total staked amounts.
    /// @param _signs is the signs of the added (true) or subtracted (false) amounts.
    /// @param _updatedStakes is the updated total staked amounts.
	function stakeChangeBatch(address[] calldata _stakeOwners, uint256[] calldata _amounts, bool[] calldata _signs, uint256[] calldata _updatedStakes) external override onlyStakingContractHandler onlyWhenActive {
		uint batchLength = _stakeOwners.length;
		require(batchLength == _amounts.length, "_stakeOwners, _amounts - array length mismatch");
		require(batchLength == _signs.length, "_stakeOwners, _signs - array length mismatch");
		require(batchLength == _updatedStakes.length, "_stakeOwners, _updatedStakes - array length mismatch");

		for (uint i = 0; i < _stakeOwners.length; i++) {
			_stakeChange(_stakeOwners[i], _updatedStakes[i]);
		}
	}

    /// Notifies of stake migration event.
    /// @dev Empty function. A staking contract migration may be handled in the future in the StakingContractHandler 
    /// @param _stakeOwner address The address of the subject stake owner.
    /// @param _amount uint256 The migrated amount.
	function stakeMigration(address _stakeOwner, uint256 _amount) external override onlyStakingContractHandler onlyWhenActive {}

	/*
	* Governance functions
	*/

    /// Imports delegations during initial migration
    /// @dev initialization function called only by the initializationManager
    /// @dev Does not update the Rewards or Election contracts
    /// @dev assumes deactivated Rewards
    /// @param from is a list of delegator addresses
    /// @param to is the address the delegators delegate to
	function importDelegations(address[] calldata from, address to) external override onlyInitializationAdmin {
		require(to != address(0), "to must be a non zero address");
		require(from.length > 0, "from array must contain at least one address");
		(uint96 stakingRewardsPerWeight, ) = stakingRewardsContract.getStakingRewardsState();
		require(stakingRewardsPerWeight == 0, "no rewards may be allocated prior to importing delegations");

		uint256 uncappedDelegatedStakeDelta = 0;
		StakeOwnerData memory data;
		uint256 newTotalDelegatedStake = totalDelegatedStake;
		DelegateStatus memory delegateStatus = getDelegateStatus(to);
		IStakingContractHandler _stakingContractHandler = stakingContractHandler;
		uint256 delegatorUncapped;
		uint256[] memory delegatorsStakes = new uint256[](from.length);
		for (uint i = 0; i < from.length; i++) {
			data = stakeOwnersData[from[i]];
			require(data.delegation == address(0), "import allowed only for uninitialized accounts. existing delegation detected");
			require(from[i] != to, "import cannot be used for self-delegation (already self delegated)");
			require(data.stake == 0 , "import allowed only for uninitialized accounts. existing stake detected");

			// from[i] stops being self delegating. any uncappedDelegatedStake it has now stops being counted towards totalDelegatedStake
			delegatorUncapped = uncappedDelegatedStake[from[i]];
			if (delegatorUncapped > 0) {
				newTotalDelegatedStake = newTotalDelegatedStake.sub(delegatorUncapped);
				emit DelegatedStakeChanged(
					from[i],
					0,
					0,
					from[i],
					0
				);
			}

			// update state
			data.delegation = to;
			data.stake = uint96(_stakingContractHandler.getStakeBalanceOf(from[i]));
			stakeOwnersData[from[i]] = data;

			uncappedDelegatedStakeDelta = uncappedDelegatedStakeDelta.add(data.stake);

			// store individual stake for event
			delegatorsStakes[i] = data.stake;

			emit Delegated(from[i], to);

			emit DelegatedStakeChanged(
				to,
				delegateStatus.selfDelegatedStake,
				delegateStatus.isSelfDelegating ? delegateStatus.delegatedStake.add(uncappedDelegatedStakeDelta) : 0,
				from[i],
				data.stake
			);
		}

		// update totals
		uncappedDelegatedStake[to] = uncappedDelegatedStake[to].add(uncappedDelegatedStakeDelta);

		if (delegateStatus.isSelfDelegating) {
			newTotalDelegatedStake = newTotalDelegatedStake.add(uncappedDelegatedStakeDelta);
		}
		totalDelegatedStake = newTotalDelegatedStake;

		// emit events
		emit DelegationsImported(from, to);
	}

    /// Initializes the delegation of an address during initial migration 
    /// @dev initialization function called only by the initializationManager
    /// @dev behaves identically to a delegate transaction sent by the delegator
    /// @param from is the delegator addresses
    /// @param to is the delegator delegates to
	function initDelegation(address from, address to) external override onlyInitializationAdmin {
		delegateFrom(from, to);
		emit DelegationInitialized(from, to);
	}

	/*
	* Private functions
	*/

    /// Generates and returns an internal memory structure with a Delegate status
    /// @dev updated based on the up to date state
    /// @dev status.addr is the queried address
    /// @dev status.uncappedDelegatedStake is the amount delegated to address including self-delegated stake
    /// @dev status.isSelfDelegating indicates whether the address is self-delegated
    /// @dev status.selfDelegatedStake if the addr is self-delegated is  the addr self stake. 0 if not self-delegated
    /// @dev status.delegatedStake if the addr is self-delegated is the mount delegated to address. 0 if not self-delegated
	function getDelegateStatus(address addr) private view returns (DelegateStatus memory status) {
		StakeOwnerData memory data = getStakeOwnerData(addr);

		status.addr = addr;
		status.uncappedDelegatedStake = uncappedDelegatedStake[addr];
		status.isSelfDelegating = data.delegation == addr;
		status.selfDelegatedStake = status.isSelfDelegating ? data.stake : 0;
		status.delegatedStake = status.isSelfDelegating ? status.uncappedDelegatedStake : 0;

		return status;
	}

    /// Returns an address stake and delegation data. 
    /// @dev implicitly self-delegated addresses (delegation = 0) return delegation to the address
	function getStakeOwnerData(address addr) private view returns (StakeOwnerData memory data) {
		data = stakeOwnersData[addr];
		data.delegation = (data.delegation == address(0)) ? addr : data.delegation;
		return data;
	}

	struct DelegateFromVars {
		DelegateStatus prevDelegateStatusBefore;
		DelegateStatus newDelegateStatusBefore;
		DelegateStatus prevDelegateStatusAfter;
		DelegateStatus newDelegateStatusAfter;
	}

    /// Handles a delegation change
    /// @dev notifies the rewards contract on the expected change (with data prior to the change)
    /// @dev updates the impacted delegates delegated stake and the total stake
    /// @dev notifies the election contract on changes in the impacted delegates delegated stake
    /// @param from is the delegator address 
    /// @param to is the delegate address
	function delegateFrom(address from, address to) private {
		require(to != address(0), "cannot delegate to a zero address");

		DelegateFromVars memory vars;

		StakeOwnerData memory delegatorData = getStakeOwnerData(from);
		address prevDelegate = delegatorData.delegation;

		if (to == prevDelegate) return; // Delegation hasn't changed

		// Optimization - no need for the full flow in the case of a zero staked delegator with no delegations
		if (delegatorData.stake == 0 && uncappedDelegatedStake[from] == 0) {
			stakeOwnersData[from].delegation = to;
			emit Delegated(from, to);
			return;
		}

		vars.prevDelegateStatusBefore = getDelegateStatus(prevDelegate);
		vars.newDelegateStatusBefore = getDelegateStatus(to);

		stakingRewardsContract.delegationWillChange(prevDelegate, vars.prevDelegateStatusBefore.delegatedStake, from, delegatorData.stake, to, vars.newDelegateStatusBefore.delegatedStake);

		stakeOwnersData[from].delegation = to;

		uint256 delegatorStake = delegatorData.stake;

		uncappedDelegatedStake[prevDelegate] = vars.prevDelegateStatusBefore.uncappedDelegatedStake.sub(delegatorStake);
		uncappedDelegatedStake[to] = vars.newDelegateStatusBefore.uncappedDelegatedStake.add(delegatorStake);

		vars.prevDelegateStatusAfter = getDelegateStatus(prevDelegate);
		vars.newDelegateStatusAfter = getDelegateStatus(to);

		uint256 _totalDelegatedStake = totalDelegatedStake.sub(
			vars.prevDelegateStatusBefore.delegatedStake
		).add(
			vars.prevDelegateStatusAfter.delegatedStake
		).sub(
			vars.newDelegateStatusBefore.delegatedStake
		).add(
			vars.newDelegateStatusAfter.delegatedStake
		);

		totalDelegatedStake = _totalDelegatedStake;

		emit Delegated(from, to);

		IElections _electionsContract = electionsContract;

		if (vars.prevDelegateStatusBefore.delegatedStake != vars.prevDelegateStatusAfter.delegatedStake) {
			_electionsContract.delegatedStakeChange(
				prevDelegate,
				vars.prevDelegateStatusAfter.selfDelegatedStake,
				vars.prevDelegateStatusAfter.delegatedStake,
				_totalDelegatedStake
			);

			emit DelegatedStakeChanged(
				prevDelegate,
				vars.prevDelegateStatusAfter.selfDelegatedStake,
				vars.prevDelegateStatusAfter.delegatedStake,
				from,
				0
			);
		}

		if (vars.newDelegateStatusBefore.delegatedStake != vars.newDelegateStatusAfter.delegatedStake) {
			_electionsContract.delegatedStakeChange(
				to,
				vars.newDelegateStatusAfter.selfDelegatedStake,
				vars.newDelegateStatusAfter.delegatedStake,
				_totalDelegatedStake
			);

			emit DelegatedStakeChanged(
				to,
				vars.newDelegateStatusAfter.selfDelegatedStake,
				vars.newDelegateStatusAfter.delegatedStake,
				from,
				delegatorStake
			);
		}
	}

    /// Handles a change in a stake owner stake
    /// @dev notifies the rewards contract on the expected change (with data prior to the change)
    /// @dev updates the impacted delegate delegated stake and the total stake
    /// @dev notifies the election contract on changes in the impacted delegate delegated stake
    /// @param _stakeOwner is the stake owner
    /// @param _updatedStake is the stake owner stake after the change
	function _stakeChange(address _stakeOwner, uint256 _updatedStake) private {
		StakeOwnerData memory stakeOwnerDataBefore = getStakeOwnerData(_stakeOwner);
		DelegateStatus memory delegateStatusBefore = getDelegateStatus(stakeOwnerDataBefore.delegation);

		uint256 prevUncappedStake = delegateStatusBefore.uncappedDelegatedStake;
		uint256 newUncappedStake = prevUncappedStake.sub(stakeOwnerDataBefore.stake).add(_updatedStake);

		stakingRewardsContract.delegationWillChange(stakeOwnerDataBefore.delegation, delegateStatusBefore.delegatedStake, _stakeOwner, stakeOwnerDataBefore.stake, stakeOwnerDataBefore.delegation, delegateStatusBefore.delegatedStake);

		uncappedDelegatedStake[stakeOwnerDataBefore.delegation] = newUncappedStake;

		require(uint256(uint96(_updatedStake)) == _updatedStake, "Delegations::updatedStakes value too big (>96 bits)");
		stakeOwnersData[_stakeOwner].stake = uint96(_updatedStake);

		uint256 _totalDelegatedStake = totalDelegatedStake;
		if (delegateStatusBefore.isSelfDelegating) {
			_totalDelegatedStake = _totalDelegatedStake.sub(stakeOwnerDataBefore.stake).add(_updatedStake);
			totalDelegatedStake = _totalDelegatedStake;
		}

		DelegateStatus memory delegateStatusAfter = getDelegateStatus(stakeOwnerDataBefore.delegation);

		electionsContract.delegatedStakeChange(
			stakeOwnerDataBefore.delegation,
			delegateStatusAfter.selfDelegatedStake,
			delegateStatusAfter.delegatedStake,
			_totalDelegatedStake
		);

		if (_updatedStake != stakeOwnerDataBefore.stake) {
			emit DelegatedStakeChanged(
				stakeOwnerDataBefore.delegation,
				delegateStatusAfter.selfDelegatedStake,
				delegateStatusAfter.delegatedStake,
				_stakeOwner,
				_updatedStake
			);
		}
	}

	/*
     * Contracts topology / registry interface
     */

	IElections electionsContract;
	IStakingRewards stakingRewardsContract;
	IStakingContractHandler stakingContractHandler;

    /// Refreshes the address of the other contracts the contract interacts with
    /// @dev called by the registry contract upon an update of a contract in the registry
	function refreshContracts() external override {
		electionsContract = IElections(getElectionsContract());
		stakingContractHandler = IStakingContractHandler(getStakingContractHandler());
		stakingRewardsContract = IStakingRewards(getStakingRewardsContract());
	}

}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IContractRegistry","name":"_contractRegistry","type":"address"},{"internalType":"address","name":"_registryAdmin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"ContractRegistryAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Delegated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"selfDelegatedStake","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"delegatedStake","type":"uint256"},{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":false,"internalType":"uint256","name":"delegatorContributedStake","type":"uint256"}],"name":"DelegatedStakeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"DelegationInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"from","type":"address[]"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"DelegationsImported","type":"event"},{"anonymous":false,"inputs":[],"name":"InitializationComplete","type":"event"},{"anonymous":false,"inputs":[],"name":"Locked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousRegistryAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newRegistryAdmin","type":"address"}],"name":"RegistryManagementTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"Unlocked","type":"event"},{"inputs":[],"name":"VOID_ADDR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRegistryManagement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getContractRegistry","outputs":[{"internalType":"contract IContractRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getDelegatedStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getDelegation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getDelegationInfo","outputs":[{"internalType":"address","name":"delegation","type":"address"},{"internalType":"uint256","name":"delegatorStake","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDelegatedStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"from","type":"address[]"},{"internalType":"address","name":"to","type":"address"}],"name":"importDelegations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"initDelegation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initializationAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initializationComplete","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isInitializationComplete","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRegistryAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"locked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingRegistryAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refreshContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"refreshStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addrs","type":"address[]"}],"name":"refreshStakeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"registryAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceRegistryManagement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IContractRegistry","name":"newContractRegistry","type":"address"}],"name":"setContractRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_registryAdmin","type":"address"}],"name":"setRegistryAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakeOwner","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"_updatedStake","type":"uint256"}],"name":"stakeChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_stakeOwners","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"bool[]","name":"_signs","type":"bool[]"},{"internalType":"uint256[]","name":"_updatedStakes","type":"uint256[]"}],"name":"stakeChangeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakeOwner","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stakeMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakeOwnersData","outputs":[{"internalType":"address","name":"delegation","type":"address"},{"internalType":"uint96","name":"stake","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newRegistryAdmin","type":"address"}],"name":"transferRegistryManagement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"uncappedDelegatedStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlock","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b506040516200368238038062003682833981810160405260408110156200003757600080fd5b50805160209091015181818181818160006200005262000171565b600080546001600160a01b0319166001600160a01b03831690811782556040519293509160008051602062003662833981519152908290a350600280546001600160a01b031916331790556001600160a01b038216620000f9576040805162461bcd60e51b815260206004820152601d60248201527f5f636f6e747261637452656769737472792063616e6e6f742062652030000000604482015290519081900360640190fd5b620001048262000175565b6200010f81620002cd565b506001199450620001209350505050565b6001600160a01b03600081905260046020527f3569f564c44c2d85a381a1123e4afebef0204e2bb799b725ae533e5c15f0829d8054919092166001600160a01b031990911617905550620003de9050565b3390565b6200017f6200035e565b620001bc5760405162461bcd60e51b815260040180806020018281038252603e815260200180620035af603e913960400191505060405180910390fd5b600354604080516301e32edf60e21b815290516001600160a01b039283169284169163078cbb7c916004808301926020929190829003018186803b1580156200020457600080fd5b505afa15801562000219573d6000803e3d6000fd5b505050506040513d60208110156200023057600080fd5b50516001600160a01b031614620002795760405162461bcd60e51b8152600401808060200182810382526041815260200180620035ed6041913960600191505060405180910390fd5b600380546001600160a01b0383166001600160a01b0319909116811790915560408051918252517ffea2d033438b968078a6264409d0104b5f3d2ce7b795afc74918e70f3534f22b9181900360200190a150565b6001600160a01b038116620003145760405162461bcd60e51b81526004018080602001828103825260348152602001806200362e6034913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216916000805160206200366283398151915291a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6003546000906001600160a01b031633148062000395575062000380620003c0565b6001600160a01b0316336001600160a01b0316145b80620003bb5750620003a6620003cf565b6001600160a01b0316336001600160a01b0316145b905090565b6000546001600160a01b031690565b6002546001600160a01b031690565b6131c180620003ee6000396000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c80638faf2f061161010f578063cf3b670b116100a2578063efb47c7e11610071578063efb47c7e1461067b578063f83d08ba146106f4578063fab46d66146106fc578063fcd13d6514610745576101f0565b8063cf3b670b1461065b578063d252352614610663578063e4e992221461066b578063eec0701f14610673576101f0565b8063a69df4b5116100de578063a69df4b514610617578063acdb8e041461061f578063ce257ab814610627578063cf30901214610653576101f0565b80638faf2f061461044b57806390ef9d3f14610453578063a39539c6146105b9578063a4e2d6341461060f576101f0565b806339069d8c116101875780635c19a95c116101565780635c19a95c146103ef5780635f94cd9c1461041557806374c16b231461041d5780637c47c16d14610425576101f0565b806339069d8c1461036d5780633dee40571461039357806348106fe3146103c15780635605a4e5146103c9576101f0565b80632987cea0116101c35780632987cea0146102f55780632a1fac721461031b5780632b29376814610323578063333df15414610365576101f0565b806305efb9ed146101f5578063071880e8146102675780630e3b7c951461029f5780631a0b2c4f146102d9575b600080fd5b6102656004803603602081101561020b57600080fd5b81019060208101813564010000000081111561022657600080fd5b82018360208201111561023857600080fd5b8035906020019184602083028401116401000000008311171561025a57600080fd5b50909250905061076b565b005b61028d6004803603602081101561027d57600080fd5b50356001600160a01b0316610896565b60408051918252519081900360200190f35b610265600480360360808110156102b557600080fd5b506001600160a01b03813516906020810135906040810135151590606001356108a8565b6102e161095b565b604080519115158252519081900360200190f35b6102656004803603602081101561030b57600080fd5b50356001600160a01b031661097f565b6102656109fc565b6103496004803603602081101561033957600080fd5b50356001600160a01b0316610aa6565b604080516001600160a01b039092168252519081900360200190f35b610349610ab8565b6102656004803603602081101561038357600080fd5b50356001600160a01b0316610ac7565b610265600480360360408110156103a957600080fd5b506001600160a01b0381358116916020013516610b2a565b6102e1610bcf565b610265600480360360208110156103df57600080fd5b50356001600160a01b0316610bdf565b6102656004803603602081101561040557600080fd5b50356001600160a01b0316610ca2565b610349610d06565b610349610d15565b61028d6004803603602081101561043b57600080fd5b50356001600160a01b0316610d24565b610349610d39565b6102656004803603608081101561046957600080fd5b81019060208101813564010000000081111561048457600080fd5b82018360208201111561049657600080fd5b803590602001918460208302840111640100000000831117156104b857600080fd5b9193909290916020810190356401000000008111156104d657600080fd5b8201836020820111156104e857600080fd5b8035906020019184602083028401116401000000008311171561050a57600080fd5b91939092909160208101903564010000000081111561052857600080fd5b82018360208201111561053a57600080fd5b8035906020019184602083028401116401000000008311171561055c57600080fd5b91939092909160208101903564010000000081111561057a57600080fd5b82018360208201111561058c57600080fd5b803590602001918460208302840111640100000000831117156105ae57600080fd5b509092509050610d5d565b6105df600480360360208110156105cf57600080fd5b50356001600160a01b0316610f11565b604080516001600160a01b0390931683526bffffffffffffffffffffffff90911660208301528051918290030190f35b6102e1610f54565b610265610f75565b61026561100b565b6102656004803603604081101561063d57600080fd5b506001600160a01b0381351690602001356110b0565b6102e1611157565b61028d611178565b61026561117e565b610349611206565b610265611215565b6102656004803603604081101561069157600080fd5b8101906020810181356401000000008111156106ac57600080fd5b8201836020820111156106be57600080fd5b803590602001918460208302840111640100000000831117156106e057600080fd5b9193509150356001600160a01b03166112d7565b610265611afd565b6107226004803603602081101561071257600080fd5b50356001600160a01b0316611baa565b604080516001600160a01b03909316835260208301919091528051918290030190f35b6102656004803603602081101561075b57600080fd5b50356001600160a01b0316611bdf565b60035474010000000000000000000000000000000000000000900460ff16156107c55760405162461bcd60e51b8152600401808060200182810382526025815260200180612dff6025913960400191505060405180910390fd5b60005b81811015610891576108898383838181106107df57fe5b6009546001600160a01b036020909202939093013581169216905063e9aea8c886868681811061080b57fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561085857600080fd5b505afa15801561086c573d6000803e3d6000fd5b505050506040513d602081101561088257600080fd5b5051611d5f565b6001016107c8565b505050565b60056020526000908152604090205481565b6009546001600160a01b031633146108f15760405162461bcd60e51b815260040180806020018281038252602a815260200180612f48602a913960400191505060405180910390fd5b60035474010000000000000000000000000000000000000000900460ff161561094b5760405162461bcd60e51b8152600401808060200182810382526025815260200180612dff6025913960400191505060405180910390fd5b6109558482611d5f565b50505050565b600080546001600160a01b03166109706120c3565b6001600160a01b031614905090565b61098761095b565b6109c25760405162461bcd60e51b815260040180806020018281038252604081526020018061311e6040913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610a04610ab8565b6001600160a01b0316336001600160a01b031614610a535760405162461bcd60e51b8152600401808060200182810382526026815260200180612ef66026913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556040517f2a2b3ea974fb057582c3b210ef8b5f81492d15673f49d4384bfa3b896a964c3c90600090a1565b6000610ab1826120c7565b5192915050565b6002546001600160a01b031690565b610acf610ab8565b6001600160a01b0316336001600160a01b031614610b1e5760405162461bcd60e51b8152600401808060200182810382526026815260200180612ef66026913960400191505060405180910390fd5b610b2781612146565b50565b610b32610ab8565b6001600160a01b0316336001600160a01b031614610b815760405162461bcd60e51b8152600401808060200182810382526026815260200180612ef66026913960400191505060405180910390fd5b610b8b82826121fe565b806001600160a01b0316826001600160a01b03167fcf1993798656f790fc10bf446b6c785f2df06395b16dbb876003a2b018a6465860405160405180910390a35050565b6002546001600160a01b03161590565b60035474010000000000000000000000000000000000000000900460ff1615610c395760405162461bcd60e51b8152600401808060200182810382526025815260200180612dff6025913960400191505060405180910390fd5b600954604080517fe9aea8c80000000000000000000000000000000000000000000000000000000081526001600160a01b0380851660048301529151610b27938593169163e9aea8c8916024808301926020929190829003018186803b15801561085857600080fd5b60035474010000000000000000000000000000000000000000900460ff1615610cfc5760405162461bcd60e51b8152600401808060200182810382526025815260200180612dff6025913960400191505060405180910390fd5b610b2733826121fe565b6001546001600160a01b031690565b6000546001600160a01b031690565b6000610d2f826127bd565b6060015192915050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6009546001600160a01b03163314610da65760405162461bcd60e51b815260040180806020018281038252602a815260200180612f48602a913960400191505060405180910390fd5b60035474010000000000000000000000000000000000000000900460ff1615610e005760405162461bcd60e51b8152600401808060200182810382526025815260200180612dff6025913960400191505060405180910390fd5b86858114610e3f5760405162461bcd60e51b815260040180806020018281038252602e81526020018061315e602e913960400191505060405180910390fd5b808414610e7d5760405162461bcd60e51b815260040180806020018281038252602c815260200180612f1c602c913960400191505060405180910390fd5b808214610ebb5760405162461bcd60e51b8152600401808060200182810382526034815260200180612f726034913960400191505060405180910390fd5b60005b88811015610f0557610efd8a8a83818110610ed557fe5b905060200201356001600160a01b0316858584818110610ef157fe5b90506020020135611d5f565b600101610ebe565b50505050505050505050565b6004602052600090815260409020546001600160a01b038116907401000000000000000000000000000000000000000090046bffffffffffffffffffffffff1682565b60035474010000000000000000000000000000000000000000900460ff1690565b610f7d61284f565b610fb85760405162461bcd60e51b8152600401808060200182810382526023815260200180612fe06023913960400191505060405180910390fd5b600380547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f19aad37188a1d3921e29eb3c66acf43d81975e107cb650d58cca878627955fd690600090a1565b61101361095b565b61104e5760405162461bcd60e51b815260040180806020018281038252604081526020018061311e6040913960400191505060405180910390fd5b600080546040516001600160a01b03909116907f1f5f028be638d6a0e3b8d56fd05b812ce325cc8dc73cdb0e16df94d6b2725c2e908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6009546001600160a01b031633146110f95760405162461bcd60e51b815260040180806020018281038252602a815260200180612f48602a913960400191505060405180910390fd5b60035474010000000000000000000000000000000000000000900460ff16156111535760405162461bcd60e51b8152600401808060200182810382526025815260200180612dff6025913960400191505060405180910390fd5b5050565b60035474010000000000000000000000000000000000000000900460ff1681565b60065490565b6001546001600160a01b031633146111c75760405162461bcd60e51b8152600401808060200182810382526027815260200180612ecf6027913960400191505060405180910390fd5b6001546111dc906001600160a01b0316612146565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6003546001600160a01b031690565b61121d612894565b600780547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039290921691909117905561125d612955565b600980547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039290921691909117905561129d6129e5565b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6112df610ab8565b6001600160a01b0316336001600160a01b03161461132e5760405162461bcd60e51b8152600401808060200182810382526026815260200180612ef66026913960400191505060405180910390fd5b6001600160a01b038116611389576040805162461bcd60e51b815260206004820152601d60248201527f746f206d7573742062652061206e6f6e207a65726f2061646472657373000000604482015290519081900360640190fd5b816113c55760405162461bcd60e51b815260040180806020018281038252602c815260200180612ea3602c913960400191505060405180910390fd5b600854604080517fcfbe49f200000000000000000000000000000000000000000000000000000000815281516000936001600160a01b03169263cfbe49f29260048082019391829003018186803b15801561141f57600080fd5b505afa158015611433573d6000803e3d6000fd5b505050506040513d604081101561144957600080fd5b505190506bffffffffffffffffffffffff8116156114985760405162461bcd60e51b815260040180806020018281038252603a815260200180612fa6603a913960400191505060405180910390fd5b60006114a2612d38565b6006546114ad612d4f565b6114b6866127bd565b6009549091506001600160a01b0316600060608967ffffffffffffffff811180156114e057600080fd5b5060405190808252806020026020018201604052801561150a578160200160208202803683370190505b50905060005b8a811015611a0757600460008d8d8481811061152857fe5b602090810292909201356001600160a01b03908116845283830194909452506040918201600020825180840190935254928316808352740100000000000000000000000000000000000000009093046bffffffffffffffffffffffff16908201529750156115c75760405162461bcd60e51b815260040180806020018281038252604c81526020018061307d604c913960600191505060405180910390fd5b896001600160a01b03168c8c838181106115dd57fe5b905060200201356001600160a01b03166001600160a01b031614156116335760405162461bcd60e51b8152600401808060200182810382526042815260200180612dbd6042913960600191505060405180910390fd5b60208701516bffffffffffffffffffffffff16156116825760405162461bcd60e51b81526004018080602001828103825260478152602001806130366047913960600191505060405180910390fd5b600560008d8d8481811061169257fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b03168152602001908152602001600020549250600083111561176e576116d88684612a75565b95508b8b828181106116e657fe5b905060200201356001600160a01b03166001600160a01b03168c8c8381811061170b57fe5b905060200201356001600160a01b03166001600160a01b03167f52db726bc1b1643b24886ed6f0194a41de9abac79d1c12108aca494e5b2bda6b600080600060405180848152602001838152602001828152602001935050505060405180910390a35b6001600160a01b03808b168852841663e9aea8c88d8d8481811061178e57fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156117db57600080fd5b505afa1580156117ef573d6000803e3d6000fd5b505050506040513d602081101561180557600080fd5b50516bffffffffffffffffffffffff16602088015286600460008e8e8581811061182b57fe5b602090810292909201356001600160a01b0390811684528383019490945250604090910160002083518154948301517fffffffffffffffffffffffff000000000000000000000000000000000000000090951690841617909216740100000000000000000000000000000000000000006bffffffffffffffffffffffff94851602179091558801516118bf918a9116612abe565b975086602001516bffffffffffffffffffffffff168282815181106118e057fe5b602002602001018181525050896001600160a01b03168c8c8381811061190257fe5b905060200201356001600160a01b03166001600160a01b03167f4bc154dd35d6a5cb9206482ecb473cdbf2473006d6bce728b9cc0741bcc59ea260405160405180910390a38b8b8281811061195357fe5b905060200201356001600160a01b03166001600160a01b03168a6001600160a01b03167f52db726bc1b1643b24886ed6f0194a41de9abac79d1c12108aca494e5b2bda6b876080015188604001516119ac5760006119bb565b60608901516119bb908d612abe565b8b6020015160405180846bffffffffffffffffffffffff168152602001838152602001826bffffffffffffffffffffffff168152602001935050505060405180910390a3600101611510565b506001600160a01b038916600090815260056020526040902054611a2b9088612abe565b6001600160a01b038a16600090815260056020526040908190209190915584015115611a5e57611a5b8588612abe565b94505b84600681905550886001600160a01b03167f7bedb97dca1b1ff98032eb6dad66e46016096d6341192dc7c3b1be79b0b1a93a8c8c60405180806020018281038252848482818152602001925060200280828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a25050505050505050505050565b611b0561284f565b611b405760405162461bcd60e51b8152600401808060200182810382526023815260200180612fe06023913960400191505060405180910390fd5b600380547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f0f2e5b6c72c6a4491efd919a9f9a409f324ef0708c11ee57d410c2cb06c0992b90600090a1565b600080611bb5612d38565b611bbe846120c7565b80516020909101519093506bffffffffffffffffffffffff16915050915091565b611be7612b18565b611c225760405162461bcd60e51b815260040180806020018281038252603e815260200180612e24603e913960400191505060405180910390fd5b600354604080517f078cbb7c00000000000000000000000000000000000000000000000000000000815290516001600160a01b039283169284169163078cbb7c916004808301926020929190829003018186803b158015611c8257600080fd5b505afa158015611c96573d6000803e3d6000fd5b505050506040513d6020811015611cac57600080fd5b50516001600160a01b031614611cf35760405162461bcd60e51b8152600401808060200182810382526041815260200180612e626041913960600191505060405180910390fd5b600380546001600160a01b0383167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517ffea2d033438b968078a6264409d0104b5f3d2ce7b795afc74918e70f3534f22b9181900360200190a150565b611d67612d38565b611d70836120c7565b9050611d7a612d4f565b8151611d85906127bd565b90506000816020015190506000611dc185611dbb86602001516bffffffffffffffffffffffff1685612a7590919063ffffffff16565b90612abe565b600854855160608601516020880151604080517f8a1f3c020000000000000000000000000000000000000000000000000000000081526001600160a01b0394851660048201819052602482018590528d861660448301526bffffffffffffffffffffffff9093166064820152608481019290925260a48201929092529051939450911691638a1f3c029160c48082019260009290919082900301818387803b158015611e6c57600080fd5b505af1158015611e80573d6000803e3d6000fd5b505085516001600160a01b0316600090815260056020526040902083905550506bffffffffffffffffffffffff85168514611eec5760405162461bcd60e51b81526004018080602001828103825260338152602001806130036033913960400191505060405180910390fd5b6001600160a01b03868116600090815260046020526040908190208054909216740100000000000000000000000000000000000000006bffffffffffffffffffffffff891602179091556006549084015115611f7357611f6b86611dbb87602001516bffffffffffffffffffffffff1684612a7590919063ffffffff16565b600681905590505b611f7b612d4f565b8551611f86906127bd565b600754875160808301516060840151604080517f61885df80000000000000000000000000000000000000000000000000000000081526001600160a01b0394851660048201526bffffffffffffffffffffffff9093166024840152604483019190915260648201879052519394509116916361885df89160848082019260009290919082900301818387803b15801561201e57600080fd5b505af1158015612032573d6000803e3d6000fd5b5050505085602001516bffffffffffffffffffffffff1687146120b95785516080820151606080840151604080516bffffffffffffffffffffffff909416845260208401919091528281018b9052516001600160a01b03808d169416927f52db726bc1b1643b24886ed6f0194a41de9abac79d1c12108aca494e5b2bda6b92908290030190a35b5050505050505050565b3390565b6120cf612d38565b506001600160a01b03818116600090815260046020908152604091829020825180840190935254928316808352740100000000000000000000000000000000000000009093046bffffffffffffffffffffffff16908201529015612134578051612136565b815b6001600160a01b03168152919050565b6001600160a01b03811661218b5760405162461bcd60e51b81526004018080602001828103825260348152602001806130c96034913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f1f5f028be638d6a0e3b8d56fd05b812ce325cc8dc73cdb0e16df94d6b2725c2e91a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6001600160a01b0381166122435760405162461bcd60e51b81526004018080602001828103825260218152602001806130fd6021913960400191505060405180910390fd5b61224b612d7d565b612253612d38565b61225c846120c7565b80519091506001600160a01b03848116908216141561227d57505050611153565b60208201516bffffffffffffffffffffffff161580156122b357506001600160a01b038516600090815260056020526040902054155b1561232b576001600160a01b0385811660008181526004602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169489169485179055517f4bc154dd35d6a5cb9206482ecb473cdbf2473006d6bce728b9cc0741bcc59ea29190a3505050611153565b612334816127bd565b835261233f846127bd565b6020808501829052600854855160609081015192860151930151604080517f8a1f3c020000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260248201959095528a851660448201526bffffffffffffffffffffffff9095166064860152888416608486015260a485019190915251911691638a1f3c029160c480830192600092919082900301818387803b1580156123ef57600080fd5b505af1158015612403573d6000803e3d6000fd5b505050506001600160a01b03858116600090815260046020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001692871692909217909155828101518451909101516bffffffffffffffffffffffff909116906124769082612a75565b6001600160a01b0383166000908152600560209081526040909120919091558481015101516124a59082612abe565b6001600160a01b0386166000908152600560205260409020556124c7826127bd565b60408501526124d5856127bd565b84606001819052506000612526856060015160600151611dbb876020015160600151612520896040015160600151611dbb8b6000015160600151600654612a7590919063ffffffff16565b90612a75565b60068190556040519091506001600160a01b0380881691908916907f4bc154dd35d6a5cb9206482ecb473cdbf2473006d6bce728b9cc0741bcc59ea290600090a360075460408601516060908101518751909101516001600160a01b03909216911461269457806001600160a01b03166361885df885886040015160800151896040015160600151866040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846bffffffffffffffffffffffff168152602001838152602001828152602001945050505050600060405180830381600087803b15801561261157600080fd5b505af1158015612625573d6000803e3d6000fd5b505050604080880151608081015160609182015183516bffffffffffffffffffffffff9092168252602082015260008184015291516001600160a01b03808d1694508816927f52db726bc1b1643b24886ed6f0194a41de9abac79d1c12108aca494e5b2bda6b92908290030190a35b856060015160600151866020015160600151146120b957806001600160a01b03166361885df888886060015160800151896060015160600151866040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846bffffffffffffffffffffffff168152602001838152602001828152602001945050505050600060405180830381600087803b15801561273057600080fd5b505af1158015612744573d6000803e3d6000fd5b505050606080880151608081015190820151604080516bffffffffffffffffffffffff90931683526020830191909152818101879052516001600160a01b03808d1694508b16927f52db726bc1b1643b24886ed6f0194a41de9abac79d1c12108aca494e5b2bda6b928290030190a35050505050505050565b6127c5612d4f565b6127cd612d38565b6127d6836120c7565b6001600160a01b03808516808552600081815260056020908152604091829020549087015283519092161490840181905290915061281557600061281b565b80602001515b6bffffffffffffffffffffffff166080830152604082015161283e576000612844565b81602001515b606083015250919050565b600061288f6040518060400160405280601081526020017f6d6967726174696f6e4d616e6167657200000000000000000000000000000000815250612b73565b905090565b600354604080517f35817773000000000000000000000000000000000000000000000000000000008152602060048201819052600960248301527f656c656374696f6e730000000000000000000000000000000000000000000000604483015291516000936001600160a01b03169263358177739260648082019391829003018186803b15801561292457600080fd5b505afa158015612938573d6000803e3d6000fd5b505050506040513d602081101561294e57600080fd5b5051905090565b600354604080517f35817773000000000000000000000000000000000000000000000000000000008152602060048201819052601660248301527f7374616b696e67436f6e747261637448616e646c657200000000000000000000604483015291516000936001600160a01b03169263358177739260648082019391829003018186803b15801561292457600080fd5b600354604080517f35817773000000000000000000000000000000000000000000000000000000008152602060048201819052600e60248301527f7374616b696e6752657761726473000000000000000000000000000000000000604483015291516000936001600160a01b03169263358177739260648082019391829003018186803b15801561292457600080fd5b6000612ab783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612ca1565b9392505050565b600082820183811015612ab7576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6003546000906001600160a01b0316331480612b4c5750612b37610d15565b6001600160a01b0316336001600160a01b0316145b8061288f5750612b5a610ab8565b6001600160a01b0316336001600160a01b031614905090565b6003546000906001600160a01b0316612b8a612b18565b80612ab757506001600160a01b03811615801590612ab757506003546040517f1ee441e900000000000000000000000000000000000000000000000000000000815260206004820181815286516024840152865133946001600160a01b031693631ee441e99389939283926044019185019080838360005b83811015612c1a578181015183820152602001612c02565b50505050905090810190601f168015612c475780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b158015612c6457600080fd5b505afa158015612c78573d6000803e3d6000fd5b505050506040513d6020811015612c8e57600080fd5b50516001600160a01b0316149392505050565b60008184841115612d305760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612cf5578181015183820152602001612cdd565b50505050905090810190601f168015612d225780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b604080518082019091526000808252602082015290565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b6040518060800160405280612d90612d4f565b8152602001612d9d612d4f565b8152602001612daa612d4f565b8152602001612db7612d4f565b90529056fe696d706f72742063616e6e6f74206265207573656420666f722073656c662d64656c65676174696f6e2028616c72656164792073656c662064656c65676174656429636f6e7472616374206973206c6f636b656420666f722074686973206f7065726174696f6e73656e646572206973206e6f7420616e2061646d696e202872656769737472794d616e676572206f7220696e697469616c697a6174696f6e41646d696e296e657720636f6e7472616374207265676973747279206d7573742070726f76696465207468652070726576696f757320636f6e747261637420726567697374727966726f6d206172726179206d75737420636f6e7461696e206174206c65617374206f6e65206164647265737343616c6c6572206973206e6f74207468652070656e64696e6720726567697374727941646d696e73656e646572206973206e6f742074686520696e697469616c697a6174696f6e2061646d696e5f7374616b654f776e6572732c205f7369676e73202d206172726179206c656e677468206d69736d6174636863616c6c6572206973206e6f7420746865207374616b696e6720636f6e74726163742068616e646c65725f7374616b654f776e6572732c205f757064617465645374616b6573202d206172726179206c656e677468206d69736d617463686e6f2072657761726473206d617920626520616c6c6f6361746564207072696f7220746f20696d706f7274696e672064656c65676174696f6e7373656e646572206973206e6f7420746865206d6967726174696f6e206d616e6167657244656c65676174696f6e733a3a757064617465645374616b65732076616c756520746f6f2062696720283e3936206269747329696d706f727420616c6c6f776564206f6e6c7920666f7220756e696e697469616c697a6564206163636f756e74732e206578697374696e67207374616b65206465746563746564696d706f727420616c6c6f776564206f6e6c7920666f7220756e696e697469616c697a6564206163636f756e74732e206578697374696e672064656c65676174696f6e206465746563746564526567697374727941646d696e3a206e657720726567697374727941646d696e20697320746865207a65726f206164647265737363616e6e6f742064656c656761746520746f2061207a65726f206164647265737357697468436c61696d61626c6552656769737472794d616e6167656d656e743a2063616c6c6572206973206e6f742074686520726567697374727941646d696e5f7374616b654f776e6572732c205f616d6f756e7473202d206172726179206c656e677468206d69736d61746368a2646970667358221220190f4d45b81ab198cc49e7d4a1fbb315f40402e0142e6481bfbe091e58ec836064736f6c634300060c003373656e646572206973206e6f7420616e2061646d696e202872656769737472794d616e676572206f7220696e697469616c697a6174696f6e41646d696e296e657720636f6e7472616374207265676973747279206d7573742070726f76696465207468652070726576696f757320636f6e7472616374207265676973747279526567697374727941646d696e3a206e657720726567697374727941646d696e20697320746865207a65726f20616464726573731f5f028be638d6a0e3b8d56fd05b812ce325cc8dc73cdb0e16df94d6b2725c2e000000000000000000000000d859701c81119ab12a1e62af6270ad2ae05c7ab3000000000000000000000000f1fd5233e60e7ef797025fe9dd066d60d59bcb92

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101f05760003560e01c80638faf2f061161010f578063cf3b670b116100a2578063efb47c7e11610071578063efb47c7e1461067b578063f83d08ba146106f4578063fab46d66146106fc578063fcd13d6514610745576101f0565b8063cf3b670b1461065b578063d252352614610663578063e4e992221461066b578063eec0701f14610673576101f0565b8063a69df4b5116100de578063a69df4b514610617578063acdb8e041461061f578063ce257ab814610627578063cf30901214610653576101f0565b80638faf2f061461044b57806390ef9d3f14610453578063a39539c6146105b9578063a4e2d6341461060f576101f0565b806339069d8c116101875780635c19a95c116101565780635c19a95c146103ef5780635f94cd9c1461041557806374c16b231461041d5780637c47c16d14610425576101f0565b806339069d8c1461036d5780633dee40571461039357806348106fe3146103c15780635605a4e5146103c9576101f0565b80632987cea0116101c35780632987cea0146102f55780632a1fac721461031b5780632b29376814610323578063333df15414610365576101f0565b806305efb9ed146101f5578063071880e8146102675780630e3b7c951461029f5780631a0b2c4f146102d9575b600080fd5b6102656004803603602081101561020b57600080fd5b81019060208101813564010000000081111561022657600080fd5b82018360208201111561023857600080fd5b8035906020019184602083028401116401000000008311171561025a57600080fd5b50909250905061076b565b005b61028d6004803603602081101561027d57600080fd5b50356001600160a01b0316610896565b60408051918252519081900360200190f35b610265600480360360808110156102b557600080fd5b506001600160a01b03813516906020810135906040810135151590606001356108a8565b6102e161095b565b604080519115158252519081900360200190f35b6102656004803603602081101561030b57600080fd5b50356001600160a01b031661097f565b6102656109fc565b6103496004803603602081101561033957600080fd5b50356001600160a01b0316610aa6565b604080516001600160a01b039092168252519081900360200190f35b610349610ab8565b6102656004803603602081101561038357600080fd5b50356001600160a01b0316610ac7565b610265600480360360408110156103a957600080fd5b506001600160a01b0381358116916020013516610b2a565b6102e1610bcf565b610265600480360360208110156103df57600080fd5b50356001600160a01b0316610bdf565b6102656004803603602081101561040557600080fd5b50356001600160a01b0316610ca2565b610349610d06565b610349610d15565b61028d6004803603602081101561043b57600080fd5b50356001600160a01b0316610d24565b610349610d39565b6102656004803603608081101561046957600080fd5b81019060208101813564010000000081111561048457600080fd5b82018360208201111561049657600080fd5b803590602001918460208302840111640100000000831117156104b857600080fd5b9193909290916020810190356401000000008111156104d657600080fd5b8201836020820111156104e857600080fd5b8035906020019184602083028401116401000000008311171561050a57600080fd5b91939092909160208101903564010000000081111561052857600080fd5b82018360208201111561053a57600080fd5b8035906020019184602083028401116401000000008311171561055c57600080fd5b91939092909160208101903564010000000081111561057a57600080fd5b82018360208201111561058c57600080fd5b803590602001918460208302840111640100000000831117156105ae57600080fd5b509092509050610d5d565b6105df600480360360208110156105cf57600080fd5b50356001600160a01b0316610f11565b604080516001600160a01b0390931683526bffffffffffffffffffffffff90911660208301528051918290030190f35b6102e1610f54565b610265610f75565b61026561100b565b6102656004803603604081101561063d57600080fd5b506001600160a01b0381351690602001356110b0565b6102e1611157565b61028d611178565b61026561117e565b610349611206565b610265611215565b6102656004803603604081101561069157600080fd5b8101906020810181356401000000008111156106ac57600080fd5b8201836020820111156106be57600080fd5b803590602001918460208302840111640100000000831117156106e057600080fd5b9193509150356001600160a01b03166112d7565b610265611afd565b6107226004803603602081101561071257600080fd5b50356001600160a01b0316611baa565b604080516001600160a01b03909316835260208301919091528051918290030190f35b6102656004803603602081101561075b57600080fd5b50356001600160a01b0316611bdf565b60035474010000000000000000000000000000000000000000900460ff16156107c55760405162461bcd60e51b8152600401808060200182810382526025815260200180612dff6025913960400191505060405180910390fd5b60005b81811015610891576108898383838181106107df57fe5b6009546001600160a01b036020909202939093013581169216905063e9aea8c886868681811061080b57fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561085857600080fd5b505afa15801561086c573d6000803e3d6000fd5b505050506040513d602081101561088257600080fd5b5051611d5f565b6001016107c8565b505050565b60056020526000908152604090205481565b6009546001600160a01b031633146108f15760405162461bcd60e51b815260040180806020018281038252602a815260200180612f48602a913960400191505060405180910390fd5b60035474010000000000000000000000000000000000000000900460ff161561094b5760405162461bcd60e51b8152600401808060200182810382526025815260200180612dff6025913960400191505060405180910390fd5b6109558482611d5f565b50505050565b600080546001600160a01b03166109706120c3565b6001600160a01b031614905090565b61098761095b565b6109c25760405162461bcd60e51b815260040180806020018281038252604081526020018061311e6040913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610a04610ab8565b6001600160a01b0316336001600160a01b031614610a535760405162461bcd60e51b8152600401808060200182810382526026815260200180612ef66026913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556040517f2a2b3ea974fb057582c3b210ef8b5f81492d15673f49d4384bfa3b896a964c3c90600090a1565b6000610ab1826120c7565b5192915050565b6002546001600160a01b031690565b610acf610ab8565b6001600160a01b0316336001600160a01b031614610b1e5760405162461bcd60e51b8152600401808060200182810382526026815260200180612ef66026913960400191505060405180910390fd5b610b2781612146565b50565b610b32610ab8565b6001600160a01b0316336001600160a01b031614610b815760405162461bcd60e51b8152600401808060200182810382526026815260200180612ef66026913960400191505060405180910390fd5b610b8b82826121fe565b806001600160a01b0316826001600160a01b03167fcf1993798656f790fc10bf446b6c785f2df06395b16dbb876003a2b018a6465860405160405180910390a35050565b6002546001600160a01b03161590565b60035474010000000000000000000000000000000000000000900460ff1615610c395760405162461bcd60e51b8152600401808060200182810382526025815260200180612dff6025913960400191505060405180910390fd5b600954604080517fe9aea8c80000000000000000000000000000000000000000000000000000000081526001600160a01b0380851660048301529151610b27938593169163e9aea8c8916024808301926020929190829003018186803b15801561085857600080fd5b60035474010000000000000000000000000000000000000000900460ff1615610cfc5760405162461bcd60e51b8152600401808060200182810382526025815260200180612dff6025913960400191505060405180910390fd5b610b2733826121fe565b6001546001600160a01b031690565b6000546001600160a01b031690565b6000610d2f826127bd565b6060015192915050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6009546001600160a01b03163314610da65760405162461bcd60e51b815260040180806020018281038252602a815260200180612f48602a913960400191505060405180910390fd5b60035474010000000000000000000000000000000000000000900460ff1615610e005760405162461bcd60e51b8152600401808060200182810382526025815260200180612dff6025913960400191505060405180910390fd5b86858114610e3f5760405162461bcd60e51b815260040180806020018281038252602e81526020018061315e602e913960400191505060405180910390fd5b808414610e7d5760405162461bcd60e51b815260040180806020018281038252602c815260200180612f1c602c913960400191505060405180910390fd5b808214610ebb5760405162461bcd60e51b8152600401808060200182810382526034815260200180612f726034913960400191505060405180910390fd5b60005b88811015610f0557610efd8a8a83818110610ed557fe5b905060200201356001600160a01b0316858584818110610ef157fe5b90506020020135611d5f565b600101610ebe565b50505050505050505050565b6004602052600090815260409020546001600160a01b038116907401000000000000000000000000000000000000000090046bffffffffffffffffffffffff1682565b60035474010000000000000000000000000000000000000000900460ff1690565b610f7d61284f565b610fb85760405162461bcd60e51b8152600401808060200182810382526023815260200180612fe06023913960400191505060405180910390fd5b600380547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f19aad37188a1d3921e29eb3c66acf43d81975e107cb650d58cca878627955fd690600090a1565b61101361095b565b61104e5760405162461bcd60e51b815260040180806020018281038252604081526020018061311e6040913960400191505060405180910390fd5b600080546040516001600160a01b03909116907f1f5f028be638d6a0e3b8d56fd05b812ce325cc8dc73cdb0e16df94d6b2725c2e908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6009546001600160a01b031633146110f95760405162461bcd60e51b815260040180806020018281038252602a815260200180612f48602a913960400191505060405180910390fd5b60035474010000000000000000000000000000000000000000900460ff16156111535760405162461bcd60e51b8152600401808060200182810382526025815260200180612dff6025913960400191505060405180910390fd5b5050565b60035474010000000000000000000000000000000000000000900460ff1681565b60065490565b6001546001600160a01b031633146111c75760405162461bcd60e51b8152600401808060200182810382526027815260200180612ecf6027913960400191505060405180910390fd5b6001546111dc906001600160a01b0316612146565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6003546001600160a01b031690565b61121d612894565b600780547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039290921691909117905561125d612955565b600980547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039290921691909117905561129d6129e5565b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6112df610ab8565b6001600160a01b0316336001600160a01b03161461132e5760405162461bcd60e51b8152600401808060200182810382526026815260200180612ef66026913960400191505060405180910390fd5b6001600160a01b038116611389576040805162461bcd60e51b815260206004820152601d60248201527f746f206d7573742062652061206e6f6e207a65726f2061646472657373000000604482015290519081900360640190fd5b816113c55760405162461bcd60e51b815260040180806020018281038252602c815260200180612ea3602c913960400191505060405180910390fd5b600854604080517fcfbe49f200000000000000000000000000000000000000000000000000000000815281516000936001600160a01b03169263cfbe49f29260048082019391829003018186803b15801561141f57600080fd5b505afa158015611433573d6000803e3d6000fd5b505050506040513d604081101561144957600080fd5b505190506bffffffffffffffffffffffff8116156114985760405162461bcd60e51b815260040180806020018281038252603a815260200180612fa6603a913960400191505060405180910390fd5b60006114a2612d38565b6006546114ad612d4f565b6114b6866127bd565b6009549091506001600160a01b0316600060608967ffffffffffffffff811180156114e057600080fd5b5060405190808252806020026020018201604052801561150a578160200160208202803683370190505b50905060005b8a811015611a0757600460008d8d8481811061152857fe5b602090810292909201356001600160a01b03908116845283830194909452506040918201600020825180840190935254928316808352740100000000000000000000000000000000000000009093046bffffffffffffffffffffffff16908201529750156115c75760405162461bcd60e51b815260040180806020018281038252604c81526020018061307d604c913960600191505060405180910390fd5b896001600160a01b03168c8c838181106115dd57fe5b905060200201356001600160a01b03166001600160a01b031614156116335760405162461bcd60e51b8152600401808060200182810382526042815260200180612dbd6042913960600191505060405180910390fd5b60208701516bffffffffffffffffffffffff16156116825760405162461bcd60e51b81526004018080602001828103825260478152602001806130366047913960600191505060405180910390fd5b600560008d8d8481811061169257fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b03168152602001908152602001600020549250600083111561176e576116d88684612a75565b95508b8b828181106116e657fe5b905060200201356001600160a01b03166001600160a01b03168c8c8381811061170b57fe5b905060200201356001600160a01b03166001600160a01b03167f52db726bc1b1643b24886ed6f0194a41de9abac79d1c12108aca494e5b2bda6b600080600060405180848152602001838152602001828152602001935050505060405180910390a35b6001600160a01b03808b168852841663e9aea8c88d8d8481811061178e57fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156117db57600080fd5b505afa1580156117ef573d6000803e3d6000fd5b505050506040513d602081101561180557600080fd5b50516bffffffffffffffffffffffff16602088015286600460008e8e8581811061182b57fe5b602090810292909201356001600160a01b0390811684528383019490945250604090910160002083518154948301517fffffffffffffffffffffffff000000000000000000000000000000000000000090951690841617909216740100000000000000000000000000000000000000006bffffffffffffffffffffffff94851602179091558801516118bf918a9116612abe565b975086602001516bffffffffffffffffffffffff168282815181106118e057fe5b602002602001018181525050896001600160a01b03168c8c8381811061190257fe5b905060200201356001600160a01b03166001600160a01b03167f4bc154dd35d6a5cb9206482ecb473cdbf2473006d6bce728b9cc0741bcc59ea260405160405180910390a38b8b8281811061195357fe5b905060200201356001600160a01b03166001600160a01b03168a6001600160a01b03167f52db726bc1b1643b24886ed6f0194a41de9abac79d1c12108aca494e5b2bda6b876080015188604001516119ac5760006119bb565b60608901516119bb908d612abe565b8b6020015160405180846bffffffffffffffffffffffff168152602001838152602001826bffffffffffffffffffffffff168152602001935050505060405180910390a3600101611510565b506001600160a01b038916600090815260056020526040902054611a2b9088612abe565b6001600160a01b038a16600090815260056020526040908190209190915584015115611a5e57611a5b8588612abe565b94505b84600681905550886001600160a01b03167f7bedb97dca1b1ff98032eb6dad66e46016096d6341192dc7c3b1be79b0b1a93a8c8c60405180806020018281038252848482818152602001925060200280828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a25050505050505050505050565b611b0561284f565b611b405760405162461bcd60e51b8152600401808060200182810382526023815260200180612fe06023913960400191505060405180910390fd5b600380547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f0f2e5b6c72c6a4491efd919a9f9a409f324ef0708c11ee57d410c2cb06c0992b90600090a1565b600080611bb5612d38565b611bbe846120c7565b80516020909101519093506bffffffffffffffffffffffff16915050915091565b611be7612b18565b611c225760405162461bcd60e51b815260040180806020018281038252603e815260200180612e24603e913960400191505060405180910390fd5b600354604080517f078cbb7c00000000000000000000000000000000000000000000000000000000815290516001600160a01b039283169284169163078cbb7c916004808301926020929190829003018186803b158015611c8257600080fd5b505afa158015611c96573d6000803e3d6000fd5b505050506040513d6020811015611cac57600080fd5b50516001600160a01b031614611cf35760405162461bcd60e51b8152600401808060200182810382526041815260200180612e626041913960600191505060405180910390fd5b600380546001600160a01b0383167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517ffea2d033438b968078a6264409d0104b5f3d2ce7b795afc74918e70f3534f22b9181900360200190a150565b611d67612d38565b611d70836120c7565b9050611d7a612d4f565b8151611d85906127bd565b90506000816020015190506000611dc185611dbb86602001516bffffffffffffffffffffffff1685612a7590919063ffffffff16565b90612abe565b600854855160608601516020880151604080517f8a1f3c020000000000000000000000000000000000000000000000000000000081526001600160a01b0394851660048201819052602482018590528d861660448301526bffffffffffffffffffffffff9093166064820152608481019290925260a48201929092529051939450911691638a1f3c029160c48082019260009290919082900301818387803b158015611e6c57600080fd5b505af1158015611e80573d6000803e3d6000fd5b505085516001600160a01b0316600090815260056020526040902083905550506bffffffffffffffffffffffff85168514611eec5760405162461bcd60e51b81526004018080602001828103825260338152602001806130036033913960400191505060405180910390fd5b6001600160a01b03868116600090815260046020526040908190208054909216740100000000000000000000000000000000000000006bffffffffffffffffffffffff891602179091556006549084015115611f7357611f6b86611dbb87602001516bffffffffffffffffffffffff1684612a7590919063ffffffff16565b600681905590505b611f7b612d4f565b8551611f86906127bd565b600754875160808301516060840151604080517f61885df80000000000000000000000000000000000000000000000000000000081526001600160a01b0394851660048201526bffffffffffffffffffffffff9093166024840152604483019190915260648201879052519394509116916361885df89160848082019260009290919082900301818387803b15801561201e57600080fd5b505af1158015612032573d6000803e3d6000fd5b5050505085602001516bffffffffffffffffffffffff1687146120b95785516080820151606080840151604080516bffffffffffffffffffffffff909416845260208401919091528281018b9052516001600160a01b03808d169416927f52db726bc1b1643b24886ed6f0194a41de9abac79d1c12108aca494e5b2bda6b92908290030190a35b5050505050505050565b3390565b6120cf612d38565b506001600160a01b03818116600090815260046020908152604091829020825180840190935254928316808352740100000000000000000000000000000000000000009093046bffffffffffffffffffffffff16908201529015612134578051612136565b815b6001600160a01b03168152919050565b6001600160a01b03811661218b5760405162461bcd60e51b81526004018080602001828103825260348152602001806130c96034913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f1f5f028be638d6a0e3b8d56fd05b812ce325cc8dc73cdb0e16df94d6b2725c2e91a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6001600160a01b0381166122435760405162461bcd60e51b81526004018080602001828103825260218152602001806130fd6021913960400191505060405180910390fd5b61224b612d7d565b612253612d38565b61225c846120c7565b80519091506001600160a01b03848116908216141561227d57505050611153565b60208201516bffffffffffffffffffffffff161580156122b357506001600160a01b038516600090815260056020526040902054155b1561232b576001600160a01b0385811660008181526004602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169489169485179055517f4bc154dd35d6a5cb9206482ecb473cdbf2473006d6bce728b9cc0741bcc59ea29190a3505050611153565b612334816127bd565b835261233f846127bd565b6020808501829052600854855160609081015192860151930151604080517f8a1f3c020000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260248201959095528a851660448201526bffffffffffffffffffffffff9095166064860152888416608486015260a485019190915251911691638a1f3c029160c480830192600092919082900301818387803b1580156123ef57600080fd5b505af1158015612403573d6000803e3d6000fd5b505050506001600160a01b03858116600090815260046020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001692871692909217909155828101518451909101516bffffffffffffffffffffffff909116906124769082612a75565b6001600160a01b0383166000908152600560209081526040909120919091558481015101516124a59082612abe565b6001600160a01b0386166000908152600560205260409020556124c7826127bd565b60408501526124d5856127bd565b84606001819052506000612526856060015160600151611dbb876020015160600151612520896040015160600151611dbb8b6000015160600151600654612a7590919063ffffffff16565b90612a75565b60068190556040519091506001600160a01b0380881691908916907f4bc154dd35d6a5cb9206482ecb473cdbf2473006d6bce728b9cc0741bcc59ea290600090a360075460408601516060908101518751909101516001600160a01b03909216911461269457806001600160a01b03166361885df885886040015160800151896040015160600151866040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846bffffffffffffffffffffffff168152602001838152602001828152602001945050505050600060405180830381600087803b15801561261157600080fd5b505af1158015612625573d6000803e3d6000fd5b505050604080880151608081015160609182015183516bffffffffffffffffffffffff9092168252602082015260008184015291516001600160a01b03808d1694508816927f52db726bc1b1643b24886ed6f0194a41de9abac79d1c12108aca494e5b2bda6b92908290030190a35b856060015160600151866020015160600151146120b957806001600160a01b03166361885df888886060015160800151896060015160600151866040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846bffffffffffffffffffffffff168152602001838152602001828152602001945050505050600060405180830381600087803b15801561273057600080fd5b505af1158015612744573d6000803e3d6000fd5b505050606080880151608081015190820151604080516bffffffffffffffffffffffff90931683526020830191909152818101879052516001600160a01b03808d1694508b16927f52db726bc1b1643b24886ed6f0194a41de9abac79d1c12108aca494e5b2bda6b928290030190a35050505050505050565b6127c5612d4f565b6127cd612d38565b6127d6836120c7565b6001600160a01b03808516808552600081815260056020908152604091829020549087015283519092161490840181905290915061281557600061281b565b80602001515b6bffffffffffffffffffffffff166080830152604082015161283e576000612844565b81602001515b606083015250919050565b600061288f6040518060400160405280601081526020017f6d6967726174696f6e4d616e6167657200000000000000000000000000000000815250612b73565b905090565b600354604080517f35817773000000000000000000000000000000000000000000000000000000008152602060048201819052600960248301527f656c656374696f6e730000000000000000000000000000000000000000000000604483015291516000936001600160a01b03169263358177739260648082019391829003018186803b15801561292457600080fd5b505afa158015612938573d6000803e3d6000fd5b505050506040513d602081101561294e57600080fd5b5051905090565b600354604080517f35817773000000000000000000000000000000000000000000000000000000008152602060048201819052601660248301527f7374616b696e67436f6e747261637448616e646c657200000000000000000000604483015291516000936001600160a01b03169263358177739260648082019391829003018186803b15801561292457600080fd5b600354604080517f35817773000000000000000000000000000000000000000000000000000000008152602060048201819052600e60248301527f7374616b696e6752657761726473000000000000000000000000000000000000604483015291516000936001600160a01b03169263358177739260648082019391829003018186803b15801561292457600080fd5b6000612ab783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612ca1565b9392505050565b600082820183811015612ab7576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6003546000906001600160a01b0316331480612b4c5750612b37610d15565b6001600160a01b0316336001600160a01b0316145b8061288f5750612b5a610ab8565b6001600160a01b0316336001600160a01b031614905090565b6003546000906001600160a01b0316612b8a612b18565b80612ab757506001600160a01b03811615801590612ab757506003546040517f1ee441e900000000000000000000000000000000000000000000000000000000815260206004820181815286516024840152865133946001600160a01b031693631ee441e99389939283926044019185019080838360005b83811015612c1a578181015183820152602001612c02565b50505050905090810190601f168015612c475780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b158015612c6457600080fd5b505afa158015612c78573d6000803e3d6000fd5b505050506040513d6020811015612c8e57600080fd5b50516001600160a01b0316149392505050565b60008184841115612d305760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612cf5578181015183820152602001612cdd565b50505050905090810190601f168015612d225780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b604080518082019091526000808252602082015290565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b6040518060800160405280612d90612d4f565b8152602001612d9d612d4f565b8152602001612daa612d4f565b8152602001612db7612d4f565b90529056fe696d706f72742063616e6e6f74206265207573656420666f722073656c662d64656c65676174696f6e2028616c72656164792073656c662064656c65676174656429636f6e7472616374206973206c6f636b656420666f722074686973206f7065726174696f6e73656e646572206973206e6f7420616e2061646d696e202872656769737472794d616e676572206f7220696e697469616c697a6174696f6e41646d696e296e657720636f6e7472616374207265676973747279206d7573742070726f76696465207468652070726576696f757320636f6e747261637420726567697374727966726f6d206172726179206d75737420636f6e7461696e206174206c65617374206f6e65206164647265737343616c6c6572206973206e6f74207468652070656e64696e6720726567697374727941646d696e73656e646572206973206e6f742074686520696e697469616c697a6174696f6e2061646d696e5f7374616b654f776e6572732c205f7369676e73202d206172726179206c656e677468206d69736d6174636863616c6c6572206973206e6f7420746865207374616b696e6720636f6e74726163742068616e646c65725f7374616b654f776e6572732c205f757064617465645374616b6573202d206172726179206c656e677468206d69736d617463686e6f2072657761726473206d617920626520616c6c6f6361746564207072696f7220746f20696d706f7274696e672064656c65676174696f6e7373656e646572206973206e6f7420746865206d6967726174696f6e206d616e6167657244656c65676174696f6e733a3a757064617465645374616b65732076616c756520746f6f2062696720283e3936206269747329696d706f727420616c6c6f776564206f6e6c7920666f7220756e696e697469616c697a6564206163636f756e74732e206578697374696e67207374616b65206465746563746564696d706f727420616c6c6f776564206f6e6c7920666f7220756e696e697469616c697a6564206163636f756e74732e206578697374696e672064656c65676174696f6e206465746563746564526567697374727941646d696e3a206e657720726567697374727941646d696e20697320746865207a65726f206164647265737363616e6e6f742064656c656761746520746f2061207a65726f206164647265737357697468436c61696d61626c6552656769737472794d616e6167656d656e743a2063616c6c6572206973206e6f742074686520726567697374727941646d696e5f7374616b654f776e6572732c205f616d6f756e7473202d206172726179206c656e677468206d69736d61746368a2646970667358221220190f4d45b81ab198cc49e7d4a1fbb315f40402e0142e6481bfbe091e58ec836064736f6c634300060c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000d859701c81119ab12a1e62af6270ad2ae05c7ab3000000000000000000000000f1fd5233e60e7ef797025fe9dd066d60d59bcb92

-----Decoded View---------------
Arg [0] : _contractRegistry (address): 0xD859701C81119aB12A1e62AF6270aD2AE05c7AB3
Arg [1] : _registryAdmin (address): 0xf1fD5233E60E7Ef797025FE9DD066d60d59BcB92

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000d859701c81119ab12a1e62af6270ad2ae05c7ab3
Arg [1] : 000000000000000000000000f1fd5233e60e7ef797025fe9dd066d60d59bcb92


Deployed Bytecode Sourcemap

61371:17455:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63940:221;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;63940:221:0;;-1:-1:-1;63940:221:0;-1:-1:-1;63940:221:0;:::i;:::-;;61698:57;;;;;;;;;;;;;;;;-1:-1:-1;61698:57:0;-1:-1:-1;;;;;61698:57:0;;:::i;:::-;;;;;;;;;;;;;;;;65980:190;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;65980:190:0;;;;;;;;;;;;;;;;;;;;:::i;48702:110::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;50263:146;;;;;;;;;;;;;;;;-1:-1:-1;50263:146:0;-1:-1:-1;;;;;50263:146:0;;:::i;51789:159::-;;;:::i;64335:129::-;;;;;;;;;;;;;;;;-1:-1:-1;64335:129:0;-1:-1:-1;;;;;64335:129:0;;:::i;:::-;;;;-1:-1:-1;;;;;64335:129:0;;;;;;;;;;;;;;51594:107;;;:::i;57663:154::-;;;;;;;;;;;;;;;;-1:-1:-1;57663:154:0;-1:-1:-1;;;;;57663:154:0;;:::i;70911:165::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;70911:165:0;;;;;;;;;;:::i;52008:123::-;;;:::i;63399:145::-;;;;;;;;;;;;;;;;-1:-1:-1;63399:145:0;-1:-1:-1;;;;;63399:145:0;;:::i;62968:101::-;;;;;;;;;;;;;;;;-1:-1:-1;62968:101:0;-1:-1:-1;;;;;62968:101:0;;:::i;50777:110::-;;;:::i;48256:95::-;;;:::i;65174:137::-;;;;;;;;;;;;;;;;-1:-1:-1;65174:137:0;-1:-1:-1;;;;;65174:137:0;;:::i;61514:47::-;;;:::i;66521:658::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;66521:658:0;;-1:-1:-1;66521:658:0;-1:-1:-1;66521:658:0;:::i;61637:57::-;;;;;;;;;;;;;;;;-1:-1:-1;61637:57:0;-1:-1:-1;;;;;61637:57:0;;:::i;:::-;;;;-1:-1:-1;;;;;61637:57:0;;;;;;;;;;;;;;;;;;;;;;60370:90;;;:::i;60130:116::-;;;:::i;49206:182::-;;;:::i;67476:124::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;67476:124:0;;;;;;;;:::i;59095:18::-;;;:::i;65611:111::-;;;:::i;50515:183::-;;;:::i;57533:122::-;;;:::i;78555:266::-;;;:::i;67996:2576::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;67996:2576:0;-1:-1:-1;67996:2576:0;-1:-1:-1;;;;;67996:2576:0;;:::i;59804:111::-;;;:::i;64715:220::-;;;;;;;;;;;;;;;;-1:-1:-1;64715:220:0;-1:-1:-1;;;;;64715:220:0;;:::i;:::-;;;;-1:-1:-1;;;;;64715:220:0;;;;;;;;;;;;;;;;;;;;;56993:394;;;;;;;;;;;;;;;;-1:-1:-1;56993:394:0;-1:-1:-1;;;;;56993:394:0;;:::i;63940:221::-;60514:6;;;;;;;60513:7;60505:57;;;;-1:-1:-1;;;60505:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64036:6:::1;64031:126;64048:16:::0;;::::1;64031:126;;;64077:74;64090:5;;64096:1;64090:8;;;;;;;64100:22;::::0;-1:-1:-1;;;;;64090:8:0::1;::::0;;::::1;::::0;;;::::1;;::::0;::::1;::::0;64100:22:::1;::::0;-1:-1:-1;64100:40:0::1;64141:5:::0;;64147:1;64141:8;;::::1;;;;;;;;;;;-1:-1:-1::0;;;;;64141:8:0::1;64100:50;;;;;;;;;;;;;-1:-1:-1::0;;;;;64100:50:0::1;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;64100:50:0;64077:12:::1;:74::i;:::-;64066:3;;64031:126;;;;63940:221:::0;;:::o;61698:57::-;;;;;;;;;;;;;:::o;65980:190::-;62583:22;;-1:-1:-1;;;;;62583:22:0;62561:10;:45;62553:100;;;;-1:-1:-1;;;62553:100:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60514:6:::1;::::0;;;::::1;;;60513:7;60505:57;;;;-1:-1:-1::0;;;60505:57:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66125:40:::2;66138:11;66151:13;66125:12;:40::i;:::-;65980:190:::0;;;;:::o;48702:110::-;48750:4;48790:14;;-1:-1:-1;;;;;48790:14:0;48774:12;:10;:12::i;:::-;-1:-1:-1;;;;;48774:30:0;;48767:37;;48702:110;:::o;50263:146::-;48500:17;:15;:17::i;:::-;48492:94;;;;-1:-1:-1;;;48492:94:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50361:21:::1;:40:::0;;;::::1;-1:-1:-1::0;;;;;50361:40:0;;;::::1;::::0;;;::::1;::::0;;50263:146::o;51789:159::-;51407:21;:19;:21::i;:::-;-1:-1:-1;;;;;51393:35:0;:10;-1:-1:-1;;;;;51393:35:0;;51385:86;;;;-1:-1:-1;;;51385:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51867:20:::1;:33:::0;;;::::1;::::0;;51916:24:::1;::::0;::::1;::::0;51898:1:::1;::::0;51916:24:::1;51789:159::o:0;64335:129::-;64404:7;64425:23;64443:4;64425:17;:23::i;:::-;:34;;64335:129;-1:-1:-1;;64335:129:0:o;51594:107::-;51673:20;;-1:-1:-1;;;;;51673:20:0;51594:107;:::o;57663:154::-;51407:21;:19;:21::i;:::-;-1:-1:-1;;;;;51393:35:0;:10;-1:-1:-1;;;;;51393:35:0;;51385:86;;;;-1:-1:-1;;;51385:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57766:43:::1;57794:14;57766:27;:43::i;:::-;57663:154:::0;:::o;70911:165::-;51407:21;:19;:21::i;:::-;-1:-1:-1;;;;;51393:35:0;:10;-1:-1:-1;;;;;51393:35:0;;51385:86;;;;-1:-1:-1;;;51385:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71008:22:::1;71021:4;71027:2;71008:12;:22::i;:::-;71068:2;-1:-1:-1::0;;;;;71040:31:0::1;71062:4;-1:-1:-1::0;;;;;71040:31:0::1;;;;;;;;;;;70911:165:::0;;:::o;52008:123::-;52089:20;;-1:-1:-1;;;;;52089:20:0;:34;52008:123;:::o;63399:145::-;60514:6;;;;;;;60513:7;60505:57;;;;-1:-1:-1;;;60505:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63492:22:::1;::::0;:46:::1;::::0;;;;;-1:-1:-1;;;;;63492:46:0;;::::1;;::::0;::::1;::::0;;;63473:66:::1;::::0;63486:4;;63492:22:::1;::::0;:40:::1;::::0;:46;;;;;::::1;::::0;;;;;;;;:22;:46;::::1;;::::0;::::1;;;;::::0;::::1;62968:101:::0;60514:6;;;;;;;60513:7;60505:57;;;;-1:-1:-1;;;60505:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63036:28:::1;63049:10;63061:2;63036:12;:28::i;50777:110::-:0;50856:21;;-1:-1:-1;;;;;50856:21:0;50777:110;:::o;48256:95::-;48302:7;48329:14;-1:-1:-1;;;;;48329:14:0;48256:95;:::o;65174:137::-;65247:7;65268:23;65286:4;65268:17;:23::i;:::-;:38;;;;65174:137;-1:-1:-1;;65174:137:0:o;61514:47::-;61558:2;61514:47;:::o;66521:658::-;62583:22;;-1:-1:-1;;;;;62583:22:0;62561:10;:45;62553:100;;;;-1:-1:-1;;;62553:100:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60514:6:::1;::::0;;;::::1;;;60513:7;60505:57;;;;-1:-1:-1::0;;;60505:57:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66752:12:::0;66784:30;;::::2;66776:89;;;;-1:-1:-1::0;;;66776:89:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66878:28:::0;;::::2;66870:85;;;;-1:-1:-1::0;;;66870:85:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66968:36:::0;;::::2;66960:101;;;;-1:-1:-1::0;;;66960:101:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67073:6;67068:107;67085:23:::0;;::::2;67068:107;;;67121:48;67134:12;;67147:1;67134:15;;;;;;;;;;;;;-1:-1:-1::0;;;;;67134:15:0::2;67151:14;;67166:1;67151:17;;;;;;;;;;;;;67121:12;:48::i;:::-;67110:3;;67068:107;;;;60575:1;66521:658:::0;;;;;;;;:::o;61637:57::-;;;;;;;;;;;;-1:-1:-1;;;;;61637:57:0;;;;;;;;;:::o;60370:90::-;60446:6;;;;;;;;60370:90::o;60130:116::-;53031:20;:18;:20::i;:::-;53023:68;;;;-1:-1:-1;;;53023:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60198:6:::1;:14:::0;;;::::1;::::0;;60228:10:::1;::::0;::::1;::::0;60207:5:::1;::::0;60228:10:::1;60130:116::o:0;49206:182::-;48500:17;:15;:17::i;:::-;48492:94;;;;-1:-1:-1;;;48492:94:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49339:1:::1;49315:14:::0;;49285:57:::1;::::0;-1:-1:-1;;;;;49315:14:0;;::::1;::::0;49285:57:::1;::::0;49339:1;;49285:57:::1;49378:1;49353:27:::0;;;::::1;::::0;;49206:182::o;67476:124::-;62583:22;;-1:-1:-1;;;;;62583:22:0;62561:10;:45;62553:100;;;;-1:-1:-1;;;62553:100:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60514:6:::1;::::0;;;::::1;;;60513:7;60505:57;;;;-1:-1:-1::0;;;60505:57:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67476:124:::0;;:::o;59095:18::-;;;;;;;;;:::o;65611:111::-;65698:19;;65611:111;:::o;50515:183::-;49994:21;;-1:-1:-1;;;;;49994:21:0;49980:10;:35;49972:87;;;;-1:-1:-1;;;49972:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50623:21:::1;::::0;50595:50:::1;::::0;-1:-1:-1;;;;;50623:21:0::1;50595:27;:50::i;:::-;50656:21;:34:::0;;;::::1;::::0;;50515:183::o;57533:122::-;57631:16;;-1:-1:-1;;;;;57631:16:0;57533:122;:::o;78555:266::-;78637:22;:20;:22::i;:::-;78606:17;:54;;;;-1:-1:-1;;;;;78606:54:0;;;;;;;;;;78714:27;:25;:27::i;:::-;78665:22;:77;;;;-1:-1:-1;;;;;78665:77:0;;;;;;;;;;78788:27;:25;:27::i;:::-;78747:22;:69;;;;-1:-1:-1;;;;;78747:69:0;;;;;;;;;;78555:266::o;67996:2576::-;51407:21;:19;:21::i;:::-;-1:-1:-1;;;;;51393:35:0;:10;-1:-1:-1;;;;;51393:35:0;;51385:86;;;;-1:-1:-1;;;51385:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;68115:16:0;::::1;68107:58;;;::::0;;-1:-1:-1;;;68107:58:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;68178:15:::0;68170:72:::1;;;;-1:-1:-1::0;;;68170:72:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68284:22;::::0;:47:::1;::::0;;;;;;;68248:30:::1;::::0;-1:-1:-1;;;;;68284:22:0::1;::::0;:45:::1;::::0;:47:::1;::::0;;::::1;::::0;;;;;;;:22;:47;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;68284:47:0;;-1:-1:-1;68344:28:0::1;::::0;::::1;::::0;68336:99:::1;;;;-1:-1:-1::0;;;68336:99:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68442:35;68486:26;;:::i;:::-;68550:19;::::0;68574:36:::1;;:::i;:::-;68613:21;68631:2;68613:17;:21::i;:::-;68689:22;::::0;68574:60;;-1:-1:-1;;;;;;68689:22:0::1;68639:47;68746:33;68796:4:::0;68782:26:::1;::::0;::::1;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;68782:26:0::1;;68746:62;;68818:6;68813:1397;68830:15:::0;;::::1;68813:1397;;;68865:15;:24;68881:4;;68886:1;68881:7;;;;;;;;::::0;;::::1;::::0;;;::::1;;-1:-1:-1::0;;;;;68881:7:0;;::::1;68865:24:::0;;;;::::1;::::0;;;;-1:-1:-1;68865:24:0;;;;-1:-1:-1;68865:24:0;68858:31;;;;::::1;::::0;;;;;;::::1;::::0;;;;;;::::1;;;::::0;;::::1;::::0;;-1:-1:-1;68903:29:0;68895:118:::1;;;;-1:-1:-1::0;;;68895:118:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69038:2;-1:-1:-1::0;;;;;69027:13:0::1;:4;;69032:1;69027:7;;;;;;;;;;;;;-1:-1:-1::0;;;;;69027:7:0::1;-1:-1:-1::0;;;;;69027:13:0::1;;;69019:92;;;;-1:-1:-1::0;;;69019:92:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69125:10;::::0;::::1;::::0;:15:::1;;::::0;69117:100:::1;;;;-1:-1:-1::0;;;69117:100:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69375:22;:31;69398:4;;69403:1;69398:7;;;;;;;;;;;;;-1:-1:-1::0;;;;;69398:7:0::1;-1:-1:-1::0;;;;;69375:31:0::1;-1:-1:-1::0;;;;;69375:31:0::1;;;;;;;;;;;;;69355:51;;69436:1;69416:17;:21;69412:208;;;69471:45;:22:::0;69498:17;69471:26:::1;:45::i;:::-;69446:70;;69590:4;;69595:1;69590:7;;;;;;;;;;;;;-1:-1:-1::0;;;;;69590:7:0::1;-1:-1:-1::0;;;;;69528:85:0::1;69557:4;;69562:1;69557:7;;;;;;;;;;;;;-1:-1:-1::0;;;;;69557:7:0::1;-1:-1:-1::0;;;;;69528:85:0::1;;69572:1;69581::::0;69605::::1;69528:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69412:208;-1:-1:-1::0;;;;;69647:20:0;;::::1;::::0;;69693:41;::::1;;69735:4:::0;;69740:1;69735:7;;::::1;;;;;;;;;;;-1:-1:-1::0;;;;;69735:7:0::1;69693:50;;;;;;;;;;;;;-1:-1:-1::0;;;;;69693:50:0::1;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;69693:50:0;69673:71:::1;;69693:50;69673:10:::0;::::1;:71:::0;:4;69750:15:::1;:24;69766:4:::0;;69771:1;69766:7;;::::1;;;;;;::::0;;::::1;::::0;;;::::1;;-1:-1:-1::0;;;;;69766:7:0;;::::1;69750:24:::0;;;;::::1;::::0;;;;-1:-1:-1;69750:24:0;;;;-1:-1:-1;69750:24:0;:31;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;;::::0;;::::1;::::0;::::1;::::0;;::::1;;;::::0;;;69851:10;::::1;::::0;69819:43:::1;::::0;:27;;:43:::1;:31;:43::i;:::-;69789:73;;69932:4;:10;;;69910:32;;:16;69927:1;69910:19;;;;;;;;;;;;;:32;;;::::0;::::1;69974:2;-1:-1:-1::0;;;;;69955:22:0::1;69965:4;;69970:1;69965:7;;;;;;;;;;;;;-1:-1:-1::0;;;;;69965:7:0::1;-1:-1:-1::0;;;;;69955:22:0::1;;;;;;;;;;;70174:4;;70179:1;70174:7;;;;;;;;;;;;;-1:-1:-1::0;;;;;70174:7:0::1;-1:-1:-1::0;;;;;69990:214:0::1;70018:2;-1:-1:-1::0;;;;;69990:214:0::1;;70027:14;:33;;;70067:14;:31;;;:100;;70166:1;70067:100;;;70101:29;::::0;::::1;::::0;:62:::1;::::0;70135:27;70101:33:::1;:62::i;:::-;70188:4;:10;;;69990:214;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68847:3;;68813:1397;;;-1:-1:-1::0;;;;;;70265:26:0;::::1;;::::0;;;:22:::1;:26;::::0;;;;;:59:::1;::::0;70296:27;70265:30:::1;:59::i;:::-;-1:-1:-1::0;;;;;70236:26:0;::::1;;::::0;;;:22:::1;:26;::::0;;;;;;:88;;;;70335:31;::::1;::::0;70331:129:::1;;;70399:55;:22:::0;70426:27;70399:26:::1;:55::i;:::-;70374:80;;70331:129;70486:22;70464:19;:44;;;;70564:2;-1:-1:-1::0;;;;;70538:29:0::1;;70558:4;;70538:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;;::::1;::::0;-1:-1:-1;70538:29:0;;-1:-1:-1;;;;70538:29:0::1;51484:1;;;;;;;;67996:2576:::0;;;:::o;59804:111::-;53031:20;:18;:20::i;:::-;53023:68;;;;-1:-1:-1;;;53023:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59870:6:::1;:13:::0;;;::::1;::::0;::::1;::::0;;59899:8:::1;::::0;::::1;::::0;59870:13;;59899:8:::1;59804:111::o:0;64715:220::-;64788:18;64808:22;64837:26;;:::i;:::-;64866:23;64884:4;64866:17;:23::i;:::-;64902:15;;64919:10;;;;;64902:15;;-1:-1:-1;64894:36:0;;;-1:-1:-1;;64715:220:0;;;:::o;56993:394::-;52876:9;:7;:9::i;:::-;52868:84;;;;-1:-1:-1;;;52868:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57167:16:::1;::::0;57106:49:::1;::::0;;;;;;;-1:-1:-1;;;;;57167:16:0;;::::1;::::0;57106:47;::::1;::::0;::::1;::::0;:49:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:47;:49;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;57106:49:0;-1:-1:-1;;;;;57106:78:0::1;;57098:156;;;;-1:-1:-1::0;;;57098:156:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57265:16;:38:::0;;-1:-1:-1;;;;;57265:38:0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;57319:60:::1;::::0;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;56993:394:::0;:::o;76440:1747::-;76519:42;;:::i;:::-;76564:30;76582:11;76564:17;:30::i;:::-;76519:75;;76599:42;;:::i;:::-;76662:31;;76644:50;;:17;:50::i;:::-;76599:95;;76701:25;76729:20;:43;;;76701:71;;76777:24;76804:68;76858:13;76804:49;76826:20;:26;;;76804:49;;:17;:21;;:49;;;;:::i;:::-;:53;;:68::i;:::-;76879:22;;76923:31;;76956:35;;;;77006:26;;;;76879:224;;;;;;-1:-1:-1;;;;;76879:224:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76777:95;;-1:-1:-1;76879:22:0;;;:43;;:224;;;;;:22;;:224;;;;;;;;:22;;:224;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;77133:31:0;;-1:-1:-1;;;;;77110:55:0;;;;;:22;:55;;;;;:74;;;-1:-1:-1;;77199:30:0;;;:47;;77191:111;;;;-1:-1:-1;;;77191:111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;77307:28:0;;;;;;;:15;:28;;;;;;;:58;;;;;;;;;;;;;;77403:19;;77431:37;;;;77427:197;;;77499:71;77556:13;77499:52;77524:20;:26;;;77499:52;;:20;:24;;:52;;;;:::i;:71::-;77576:19;:42;;;77476:94;-1:-1:-1;77427:197:0;77630:41;;:::i;:::-;77692:31;;77674:50;;:17;:50::i;:::-;77731:17;;77775:31;;77812:38;;;;77856:34;;;;77731:190;;;;;;-1:-1:-1;;;;;77731:190:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77630:94;;-1:-1:-1;77731:17:0;;;:38;;:190;;;;;:17;;:190;;;;;;;;:17;;:190;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77949:20;:26;;;77932:43;;:13;:43;77928:255;;78016:31;;78054:38;;;;78099:34;;;;;77988:189;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;77988:189:0;;;;;;;;;;;;;;;77928:255;76440:1747;;;;;;;;:::o;47001:106::-;47089:10;47001:106;:::o;72380:224::-;72443:26;;:::i;:::-;-1:-1:-1;;;;;;72483:21:0;;;;;;;:15;:21;;;;;;;;;72476:28;;;;;;;;;;;;;;;;;;;;;;;;;;72528:29;72527:56;;72568:15;;72527:56;;;72561:4;72527:56;-1:-1:-1;;;;;72509:74:0;;;72380:224;;;:::o;49505:309::-;-1:-1:-1;;;;;49596:30:0;;49588:95;;;;-1:-1:-1;;;49588:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49729:14;;;49699:63;;-1:-1:-1;;;;;49699:63:0;;;;49729:14;;;49699:63;;;49773:14;:33;;;;-1:-1:-1;;;;;49773:33:0;;;;;;;;;;49505:309::o;73220:2771::-;-1:-1:-1;;;;;73289:16:0;;73281:62;;;;-1:-1:-1;;;73281:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73350:28;;:::i;:::-;73385:35;;:::i;:::-;73423:23;73441:4;73423:17;:23::i;:::-;73474:24;;73385:61;;-1:-1:-1;;;;;;73509:18:0;;;;;;;73505:31;;;73529:7;;;;;73505:31;73681:19;;;;:24;;;:61;;;;-1:-1:-1;;;;;;73709:28:0;;;;;;:22;:28;;;;;;:33;73681:61;73677:158;;;-1:-1:-1;;;;;73750:21:0;;;;;;;:15;:21;;;;;;:37;;;;;;;;;;;;73798:19;;;73750:21;73798:19;73823:7;;;;;73677:158;73873:31;73891:12;73873:17;:31::i;:::-;73841:63;;73940:21;73958:2;73940:17;:21::i;:::-;73909:28;;;;:52;;;73968:22;;74026:29;;:44;;;;;74078:19;;;;74103:43;;;73968:179;;;;;;-1:-1:-1;;;;;73968:179:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:22;;;:43;;:179;;;;;:22;;:179;;;;;;;:22;;:179;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;74154:21:0;;;;;;;:15;:21;;;;;;;;:37;;;;;;;;;;;;;;74223:19;;;;74288:29;;:52;;;;74198:44;;;;;74288:72;;74198:44;74288:56;:72::i;:::-;-1:-1:-1;;;;;74249:36:0;;;;;;:22;:36;;;;;;;;:111;;;;74394:28;;;;:51;;:71;;74450:14;74394:55;:71::i;:::-;-1:-1:-1;;;;;74365:26:0;;;;;;:22;:26;;;;;:100;74503:31;74521:12;74503:17;:31::i;:::-;74472:28;;;:62;74569:21;74587:2;74569:17;:21::i;:::-;74539:4;:27;;:51;;;;74597:28;74628:251;74832:4;:27;;;:42;;;74628:194;74774:4;:28;;;:43;;;74628:136;74716:4;:28;;;:43;;;74628:78;74657:4;:29;;;:44;;;74628:19;;:23;;:78;;;;:::i;:136::-;:140;;:194::i;:251::-;74886:19;:42;;;74940:19;;74597:282;;-1:-1:-1;;;;;;74940:19:0;;;;;;;;;;;;;74998:17;;75074:28;;;;:43;;;;;75026:29;;:44;;;;-1:-1:-1;;;;;74998:17:0;;;;75026:91;75022:486;;75125:18;-1:-1:-1;;;;;75125:39:0;;75171:12;75190:4;:28;;;:47;;;75244:4;:28;;;:43;;;75294:20;75125:195;;;;;;;;;;;;;-1:-1:-1;;;;;75125:195:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;75380:28:0;;;;;:47;;;;75434:43;;;;;75333:169;;;;;;;;;;;;75495:1;75333:169;;;;;;-1:-1:-1;;;;;75333:169:0;;;;-1:-1:-1;75333:169:0;;;;;;;;;;;;75022:486;75565:4;:27;;;:42;;;75518:4;:28;;;:43;;;:89;75514:473;;75615:18;-1:-1:-1;;;;;75615:39:0;;75661:2;75670:4;:27;;;:46;;;75723:4;:27;;;:42;;;75772:20;75615:183;;;;;;;;;;;;;-1:-1:-1;;;;;75615:183:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;75848:27:0;;;;;:46;;;;75901:42;;;;75811:170;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;75811:170:0;;;;-1:-1:-1;75811:170:0;;;;;;;;;;;73220:2771;;;;;;;;:::o;71739:480::-;71802:28;;:::i;:::-;71837:26;;:::i;:::-;71866:23;71884:4;71866:17;:23::i;:::-;-1:-1:-1;;;;;71896:18:0;;;;;;:11;71951:28;;;:22;:28;;;;;;;;;;71919:29;;;:60;72010:15;;:23;;;;71984;;;:49;;;71837:52;;-1:-1:-1;72066:40:0;;72105:1;72066:40;;;72092:4;:10;;;72066:40;72038:68;;:25;;;:68;72135:23;;;;:59;;72193:1;72135:59;;;72161:6;:29;;;72135:59;72111:21;;;:83;-1:-1:-1;71739:480:0;;;:::o;54068:114::-;54121:4;54145:29;;;;;;;;;;;;;;;;;;:9;:29::i;:::-;54138:36;;54068:114;:::o;55081:131::-;55163:16;;:41;;;;;;;;;;;;;;;;;;;;;;;;;55136:7;;-1:-1:-1;;;;;55163:16:0;;:28;;:41;;;;;;;;;;;:16;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;55163:41:0;;-1:-1:-1;55081:131:0;:::o;56563:149::-;56650:16;;:54;;;;;;;;;;;;;;;;;;;;;;;;;56623:7;;-1:-1:-1;;;;;56650:16:0;;:28;;:54;;;;;;;;;;;:16;:54;;;;;;;;;;54626:141;54713:16;;:46;;;;;;;;;;;;;;;;;;;;;;;;;54686:7;;-1:-1:-1;;;;;54713:16:0;;:28;;:46;;;;;;;;;;;:16;:46;;;;;;;;;;1420:136;1478:7;1505:43;1509:1;1512;1505:43;;;;;;;;;;;;;;;;;:3;:43::i;:::-;1498:50;1420:136;-1:-1:-1;;;1420:136:0:o;956:181::-;1014:7;1046:5;;;1070:6;;;;1062:46;;;;;-1:-1:-1;;;1062:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;53386:185;53474:16;;53428:4;;-1:-1:-1;;;;;53474:16:0;53452:10;:39;;:72;;;53509:15;:13;:15::i;:::-;-1:-1:-1;;;;;53495:29:0;:10;-1:-1:-1;;;;;53495:29:0;;53452:72;:111;;;;53542:21;:19;:21::i;:::-;-1:-1:-1;;;;;53528:35:0;:10;-1:-1:-1;;;;;53528:35:0;;53445:118;;53386:185;:::o;53736:264::-;53853:16;;53798:4;;-1:-1:-1;;;;;53853:16:0;53887:9;:7;:9::i;:::-;:105;;;-1:-1:-1;;;;;;53900:41:0;;;;;;:92;;-1:-1:-1;53945:16:0;;:33;;;;;;;;;;;;;;;;;;;;53982:10;;-1:-1:-1;;;;;53945:16:0;;:27;;53973:4;;53945:33;;;;;;;;;;;;:16;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;53945:33:0;-1:-1:-1;;;;;53945:47:0;;53880:112;53736:264;-1:-1:-1;;;53736:264:0:o;1859:192::-;1945:7;1981:12;1973:6;;;;1965:29;;;;-1:-1:-1;;;1965:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;2017:5:0;;;1859:192::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;:::o

Swarm Source

ipfs://190f4d45b81ab198cc49e7d4a1fbb315f40402e0142e6481bfbe091e58ec8360

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.