ETH Price: $3,304.50 (-3.77%)
Gas: 14 Gwei

Contract

0x01D59Af68E2dcb44e04C50e05F62E7043F2656C3
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Transaction Hash
Method
Block
From
To
Value
Withdraw202258362024-07-03 11:58:472 hrs ago1720007927IN
0x01D59Af6...43F2656C3
0 ETH0.000222354.96306879
Unstake202232882024-07-03 3:26:2311 hrs ago1719977183IN
0x01D59Af6...43F2656C3
0 ETH0.001446287.7
Unstake202222762024-07-03 0:02:3514 hrs ago1719964955IN
0x01D59Af6...43F2656C3
0 ETH0.000492092.2166249
Unstake202200322024-07-02 16:30:3522 hrs ago1719937835IN
0x01D59Af6...43F2656C3
0 ETH0.0022440610.107
Unstake202200112024-07-02 16:26:2322 hrs ago1719937583IN
0x01D59Af6...43F2656C3
0 ETH0.0026645112
Stake202162772024-07-02 3:54:1135 hrs ago1719892451IN
0x01D59Af6...43F2656C3
0 ETH0.000568312.98405369
Stake202161982024-07-02 3:38:1135 hrs ago1719891491IN
0x01D59Af6...43F2656C3
0 ETH0.001503437.7
Withdraw202161592024-07-02 3:30:2335 hrs ago1719891023IN
0x01D59Af6...43F2656C3
0 ETH0.000344977.7
Stake202124692024-07-01 15:09:3547 hrs ago1719846575IN
0x01D59Af6...43F2656C3
0 ETH0.0024687512.64324007
Unstake202102502024-07-01 7:42:592 days ago1719819779IN
0x01D59Af6...43F2656C3
0 ETH0.001110095
Unstake202095112024-07-01 5:13:592 days ago1719810839IN
0x01D59Af6...43F2656C3
0 ETH0.000581352.67603836
Withdraw202094362024-07-01 4:58:592 days ago1719809939IN
0x01D59Af6...43F2656C3
0 ETH0.000124152.00562237
Stake202090322024-07-01 3:38:112 days ago1719805091IN
0x01D59Af6...43F2656C3
0 ETH0.001503527.7
Unstake202047192024-06-30 13:11:593 days ago1719753119IN
0x01D59Af6...43F2656C3
0 ETH0.000791043.56297557
Stake202040712024-06-30 11:01:353 days ago1719745295IN
0x01D59Af6...43F2656C3
0 ETH0.001000555
Withdraw202037752024-06-30 10:02:113 days ago1719741731IN
0x01D59Af6...43F2656C3
0 ETH0.000121372.70916623
Stake201947082024-06-29 3:38:114 days ago1719632291IN
0x01D59Af6...43F2656C3
0 ETH0.001503527.7
Unstake201946822024-06-29 3:32:594 days ago1719631979IN
0x01D59Af6...43F2656C3
0 ETH0.0002981.58648139
Unstake201946702024-06-29 3:30:354 days ago1719631835IN
0x01D59Af6...43F2656C3
0 ETH0.000362851.63436408
Withdraw201936412024-06-29 0:03:114 days ago1719619391IN
0x01D59Af6...43F2656C3
0 ETH0.000127292.05638675
Withdraw201883012024-06-28 6:09:595 days ago1719554999IN
0x01D59Af6...43F2656C3
0 ETH0.000309515
Stake201875482024-06-28 3:38:235 days ago1719545903IN
0x01D59Af6...43F2656C3
0 ETH0.001503527.7
Unstake201864052024-06-27 23:48:235 days ago1719532103IN
0x01D59Af6...43F2656C3
0 ETH0.0006122.78174409
Stake201803862024-06-27 3:38:116 days ago1719459491IN
0x01D59Af6...43F2656C3
0 ETH0.001875819.606
Unstake201799602024-06-27 2:12:476 days ago1719454367IN
0x01D59Af6...43F2656C3
0 ETH0.001110035
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x0cD370eD...47D39de15
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
StakingContract

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-03-31
*/

/**

 * Orbs Staking Smart Contract
 
 *************************************************************************
 *
 * CAUTION:
 *   Staking must be done only using the contract interface functions.
 *   Do NOT transfer tokens directly to the contract address.
 *   Tokens transferred directly to the contract address are NOT staked 
 *   and CANNOT be recovered.
 *
 *************************************************************************








**/


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

pragma solidity ^0.5.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) {
        require(b <= a, "SafeMath: subtraction overflow");
        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) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        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) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol

pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see `ERC20Detailed`.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a `Transfer` event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through `transferFrom`. This is
     * zero by default.
     *
     * This value changes when `approve` or `transferFrom` are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * > Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an `Approval` event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a `Transfer` event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to `approve`. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// File: contracts/IMigratableStakingContract.sol

pragma solidity 0.5.16;


/// @title An interface for staking contracts which support stake migration.
interface IMigratableStakingContract {
    /// @dev Returns the address of the underlying staked token.
    /// @return IERC20 The address of the token.
    function getToken() external view returns (IERC20);

    /// @dev Stakes ORBS tokens on behalf of msg.sender. This method assumes that the user has already approved at least
    /// the required amount using ERC20 approve.
    /// @param _stakeOwner address The specified stake owner.
    /// @param _amount uint256 The number of tokens to stake.
    function acceptMigration(address _stakeOwner, uint256 _amount) external;

    event AcceptedMigration(address indexed stakeOwner, uint256 amount, uint256 totalStakedAmount);
}

// File: contracts/IStakingContract.sol

pragma solidity 0.5.16;


/// @title An interface for staking contracts.
interface IStakingContract {
    /// @dev Stakes ORBS tokens on behalf of msg.sender. This method assumes that the user has already approved at least
    /// the required amount using ERC20 approve.
    /// @param _amount uint256 The amount of tokens to stake.
    function stake(uint256 _amount) external;

    /// @dev Unstakes ORBS tokens from msg.sender. If successful, this will start the cooldown period, after which
    /// msg.sender would be able to withdraw all of his tokens.
    /// @param _amount uint256 The amount of tokens to unstake.
    function unstake(uint256 _amount) external;

    /// @dev Requests to withdraw all of staked ORBS tokens back to msg.sender. Stake owners can withdraw their ORBS
    /// tokens only after previously unstaking them and after the cooldown period has passed (unless the contract was
    /// requested to release all stakes).
    function withdraw() external;

    /// @dev Restakes unstaked ORBS tokens (in or after cooldown) for msg.sender.
    function restake() external;

    /// @dev Distributes staking rewards to a list of addresses by directly adding rewards to their stakes. This method
    /// assumes that the user has already approved at least the required amount using ERC20 approve. Since this is a
    /// convenience method, we aren't concerned about reaching block gas limit by using large lists. We assume that
    /// callers will be able to properly batch/paginate their requests.
    /// @param _totalAmount uint256 The total amount of rewards to distributes.
    /// @param _stakeOwners address[] The addresses of the stake owners.
    /// @param _amounts uint256[] The amounts of the rewards.
    function distributeRewards(uint256 _totalAmount, address[] calldata _stakeOwners, uint256[] calldata _amounts) external;

    /// @dev 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);

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

    /// @dev Returns the time that the cooldown period ends (or ended) and the amount of tokens to be released.
    /// @param _stakeOwner address The address to check.
    /// @return cooldownAmount uint256 The total tokens in cooldown.
    /// @return cooldownEndTime uint256 The time when the cooldown period ends (in seconds).
    function getUnstakeStatus(address _stakeOwner) external view returns (uint256 cooldownAmount,
        uint256 cooldownEndTime);

    /// @dev Migrates the stake of msg.sender from this staking contract to a new approved staking contract.
    /// @param _newStakingContract IMigratableStakingContract The new staking contract which supports stake migration.
    /// @param _amount uint256 The amount of tokens to migrate.
    function migrateStakedTokens(IMigratableStakingContract _newStakingContract, uint256 _amount) external;

    event Staked(address indexed stakeOwner, uint256 amount, uint256 totalStakedAmount);
    event Unstaked(address indexed stakeOwner, uint256 amount, uint256 totalStakedAmount);
    event Withdrew(address indexed stakeOwner, uint256 amount, uint256 totalStakedAmount);
    event Restaked(address indexed stakeOwner, uint256 amount, uint256 totalStakedAmount);
    event MigratedStake(address indexed stakeOwner, uint256 amount, uint256 totalStakedAmount);
}

// File: contracts/IStakeChangeNotifier.sol

pragma solidity 0.5.16;

/// @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/StakingContract.sol

pragma solidity 0.5.16;




/// @title Orbs staking smart contract.
contract StakingContract is IStakingContract, IMigratableStakingContract {
    using SafeMath for uint256;

    struct Stake {
        uint256 amount;
        uint256 cooldownAmount;
        uint256 cooldownEndTime;
    }

    struct WithdrawResult {
        uint256 withdrawnAmount;
        uint256 stakedAmount;
        uint256 stakedAmountDiff;
    }

    // The version of the smart contract.
    uint public constant VERSION = 1;

    // The maximum number of approved staking contracts as migration destinations.
    uint public constant MAX_APPROVED_STAKING_CONTRACTS = 10;

    // The mapping between stake owners and their data.
    mapping(address => Stake) internal stakes;

    // Total amount of staked tokens (not including unstaked tokes in cooldown or pending withdrawal).
    uint256 internal totalStakedTokens;

    // The period (in seconds) between a stake owner's request to stop staking and being able to withdraw them.
    uint256 public cooldownPeriodInSec;

    // The address responsible for managing migration to a new staking contract.
    address public migrationManager;

    // The address responsible for emergency operations and graceful return of staked tokens back to their owners.
    address public emergencyManager;

    // The list of staking contracts that are approved by this contract. It would be only allowed to migrate a stake to
    // one of these contracts.
    IMigratableStakingContract[] public approvedStakingContracts;

    // The address of the contract responsible for publishing stake change notifications.
    IStakeChangeNotifier public notifier;

    // The address of the ORBS token.
    IERC20 internal token;

    // Represents whether the contract accepts new staking requests. Please note, that even when it's turned off,
    // it'd be still possible to unstake or withdraw tokens.
    //
    // Note: This can be turned off only once by the emergency manager of the contract.
    bool public acceptingNewStakes = true;

    // Represents whether this staking contract allows releasing all unstaked tokens unconditionally. When it's turned
    // on, stake owners could release their staked tokens, without explicitly requesting to unstake them, and their
    // previously unstaked tokens, regardless of the cooldown period. This also stops the contract from accepting new
    // stakes.
    //
    // Note: This can be turned off only once by the emergency manager of the contract.
    bool public releasingAllStakes = false;

    event MigrationManagerUpdated(address indexed migrationManager);
    event MigrationDestinationAdded(IMigratableStakingContract indexed stakingContract);
    event MigrationDestinationRemoved(IMigratableStakingContract indexed stakingContract);
    event EmergencyManagerUpdated(address indexed emergencyManager);
    event StakeChangeNotifierUpdated(IStakeChangeNotifier indexed notifier);
    event StoppedAcceptingNewStake();
    event ReleasedAllStakes();

    modifier onlyMigrationManager() {
        require(msg.sender == migrationManager, "StakingContract: caller is not the migration manager");

        _;
    }

    modifier onlyEmergencyManager() {
        require(msg.sender == emergencyManager, "StakingContract: caller is not the emergency manager");

        _;
    }

    modifier onlyWhenAcceptingNewStakes() {
        require(acceptingNewStakes && !releasingAllStakes, "StakingContract: not accepting new stakes");

        _;
    }

    modifier onlyWhenStakesReleased() {
        require(releasingAllStakes, "StakingContract: not releasing all stakes");

        _;
    }

    modifier onlyWhenStakesNotReleased() {
        require(!releasingAllStakes, "StakingContract: releasing all stakes");

        _;
    }

    /// @dev Initializes the staking contract.
    /// @param _cooldownPeriodInSec uint256 The period (in seconds) between a stake owner's request to stop staking and being
    /// able to withdraw them.
    /// @param _migrationManager address The address responsible for managing migration to a new staking contract.
    /// @param _emergencyManager address The address responsible for emergency operations and graceful return of staked
    /// tokens back to their owners.
    /// @param _token IERC20 The address of the ORBS token.
    constructor(uint256 _cooldownPeriodInSec, address _migrationManager, address _emergencyManager, IERC20 _token) public {
        require(_cooldownPeriodInSec > 0, "StakingContract::ctor - cooldown period must be greater than 0");
        require(_migrationManager != address(0), "StakingContract::ctor - migration manager must not be 0");
        require(_emergencyManager != address(0), "StakingContract::ctor - emergency manager must not be 0");
        require(address(_token) != address(0), "StakingContract::ctor - ORBS token must not be 0");

        cooldownPeriodInSec = _cooldownPeriodInSec;
        migrationManager = _migrationManager;
        emergencyManager = _emergencyManager;
        token = _token;
    }

    /// @dev Sets the address of the migration manager.
    /// @param _newMigrationManager address The address of the new migration manager.
    function setMigrationManager(address _newMigrationManager) external onlyMigrationManager {
        require(_newMigrationManager != address(0), "StakingContract::setMigrationManager - address must not be 0");
        require(migrationManager != _newMigrationManager,
            "StakingContract::setMigrationManager - address must be different than the current address");

        migrationManager = _newMigrationManager;

        emit MigrationManagerUpdated(_newMigrationManager);
    }

    /// @dev Sets the address of the emergency manager.
    /// @param _newEmergencyManager address The address of the new emergency manager.
    function setEmergencyManager(address _newEmergencyManager) external onlyEmergencyManager {
        require(_newEmergencyManager != address(0), "StakingContract::setEmergencyManager - address must not be 0");
        require(emergencyManager != _newEmergencyManager,
            "StakingContract::setEmergencyManager - address must be different than the current address");

        emergencyManager = _newEmergencyManager;

        emit EmergencyManagerUpdated(_newEmergencyManager);
    }

    /// @dev Sets the address of the stake change notifier contract.
    /// @param _newNotifier IStakeChangeNotifier The address of the new stake change notifier contract.
    ///
    /// Note: it's allowed to reset the notifier to a zero address.
    function setStakeChangeNotifier(IStakeChangeNotifier _newNotifier) external onlyMigrationManager {
        require(notifier != _newNotifier,
            "StakingContract::setStakeChangeNotifier - address must be different than the current address");

        notifier = _newNotifier;

        emit StakeChangeNotifierUpdated(notifier);
    }

    /// @dev Adds a new contract to the list of approved staking contracts migration destinations.
    /// @param _newStakingContract IMigratableStakingContract The new contract to add.
    function addMigrationDestination(IMigratableStakingContract _newStakingContract) external onlyMigrationManager {
        require(address(_newStakingContract) != address(0),
            "StakingContract::addMigrationDestination - address must not be 0");

        uint length = approvedStakingContracts.length;
        require(length + 1 <= MAX_APPROVED_STAKING_CONTRACTS,
            "StakingContract::addMigrationDestination - can't add more staking contracts");

        // Check for duplicates.
        for (uint i = 0; i < length; ++i) {
            require(approvedStakingContracts[i] != _newStakingContract,
                "StakingContract::addMigrationDestination - can't add a duplicate staking contract");
        }

        approvedStakingContracts.push(_newStakingContract);

        emit MigrationDestinationAdded(_newStakingContract);
    }

    /// @dev Removes a contract from the list of approved staking contracts migration destinations.
    /// @param _stakingContract IMigratableStakingContract The contract to remove.
    function removeMigrationDestination(IMigratableStakingContract _stakingContract) external onlyMigrationManager {
        require(address(_stakingContract) != address(0),
            "StakingContract::removeMigrationDestination - address must not be 0");

        // Check for existence.
        (uint i, bool exists) = findApprovedStakingContractIndex(_stakingContract);
        require(exists, "StakingContract::removeMigrationDestination - staking contract doesn't exist");

        // Swap the requested element with the last element and then delete it using pop/
        approvedStakingContracts[i] = approvedStakingContracts[approvedStakingContracts.length - 1];
        approvedStakingContracts.pop();

        emit MigrationDestinationRemoved(_stakingContract);
    }

    /// @dev Stakes ORBS tokens on behalf of msg.sender. This method assumes that the user has already approved at least
    /// the required amount using ERC20 approve.
    /// @param _amount uint256 The amount of tokens to stake.
    function stake(uint256 _amount) external onlyWhenAcceptingNewStakes {
        address stakeOwner = msg.sender;

        uint256 totalStakedAmount = stake(stakeOwner, _amount);

        emit Staked(stakeOwner, _amount, totalStakedAmount);

        // Note: we aren't concerned with reentrancy since:
        //   1. At this point, due to the CEI pattern, a reentrant notifier can't affect the effects of this method.
        //   2. The notifier is set and managed by the migration manager.
        stakeChange(stakeOwner, _amount, true, totalStakedAmount);
    }

    /// @dev Unstakes ORBS tokens from msg.sender. If successful, this will start the cooldown period, after which
    /// msg.sender would be able to withdraw all of his tokens.
    /// @param _amount uint256 The amount of tokens to unstake.
    function unstake(uint256 _amount) external {
        require(_amount > 0, "StakingContract::unstake - amount must be greater than 0");

        address stakeOwner = msg.sender;
        Stake storage stakeData = stakes[stakeOwner];
        uint256 stakedAmount = stakeData.amount;
        uint256 cooldownAmount = stakeData.cooldownAmount;
        uint256 cooldownEndTime = stakeData.cooldownEndTime;

        require(_amount <= stakedAmount, "StakingContract::unstake - can't unstake more than the current stake");

        // If any tokens in cooldown are ready for withdrawal - revert. Stake owner should withdraw their unstaked
        // tokens first.
        require(cooldownAmount == 0 || cooldownEndTime > now,
            "StakingContract::unstake - unable to unstake when there are tokens pending withdrawal");

        // Update the amount of tokens in cooldown. Please note that this will also restart the cooldown period of all
        // tokens in cooldown.
        stakeData.amount = stakedAmount.sub(_amount);
        stakeData.cooldownAmount = cooldownAmount.add(_amount);
        stakeData.cooldownEndTime = now.add(cooldownPeriodInSec);

        totalStakedTokens = totalStakedTokens.sub(_amount);

        uint256 totalStakedAmount = stakeData.amount;

        emit Unstaked(stakeOwner, _amount, totalStakedAmount);

        // Note: we aren't concerned with reentrancy since:
        //   1. At this point, due to the CEI pattern, a reentrant notifier can't affect the effects of this method.
        //   2. The notifier is set and managed by the migration manager.
        stakeChange(stakeOwner, _amount, false, totalStakedAmount);
    }

    /// @dev Requests to withdraw all of staked ORBS tokens back to msg.sender. Stake owners can withdraw their ORBS
    /// tokens only after previously unstaking them and after the cooldown period has passed (unless the contract was
    /// requested to release all stakes).
    function withdraw() external {
        address stakeOwner = msg.sender;

        WithdrawResult memory res = withdraw(stakeOwner);

        emit Withdrew(stakeOwner, res.withdrawnAmount, res.stakedAmount);

        // Trigger staking state change notifications only if the staking amount was changed.
        if (res.stakedAmountDiff == 0) {
            return;
        }

        // Note: we aren't concerned with reentrancy since:
        //   1. At this point, due to the CEI pattern, a reentrant notifier can't affect the effects of this method.
        //   2. The notifier is set and managed by the migration manager.
        stakeChange(stakeOwner, res.stakedAmountDiff, false, res.stakedAmount);
    }

    /// @dev Restakes unstaked ORBS tokens (in or after cooldown) for msg.sender.
    function restake() external onlyWhenAcceptingNewStakes {
        address stakeOwner = msg.sender;
        Stake storage stakeData = stakes[stakeOwner];
        uint256 cooldownAmount = stakeData.cooldownAmount;

        require(cooldownAmount > 0, "StakingContract::restake - no unstaked tokens");

        stakeData.amount = stakeData.amount.add(cooldownAmount);
        stakeData.cooldownAmount = 0;
        stakeData.cooldownEndTime = 0;

        totalStakedTokens = totalStakedTokens.add(cooldownAmount);

        uint256 totalStakedAmount = stakeData.amount;

        emit Restaked(stakeOwner, cooldownAmount, totalStakedAmount);

        // Note: we aren't concerned with reentrancy since:
        //   1. At this point, due to the CEI pattern, a reentrant notifier can't affect the effects of this method.
        //   2. The notifier is set and managed by the migration manager.
        stakeChange(stakeOwner, cooldownAmount, true, totalStakedAmount);
    }

    /// @dev Stakes ORBS tokens on behalf of msg.sender. This method assumes that the user has already approved at least
    /// the required amount using ERC20 approve.
    /// @param _stakeOwner address The specified stake owner.
    /// @param _amount uint256 The amount of tokens to stake.
    function acceptMigration(address _stakeOwner, uint256 _amount) external onlyWhenAcceptingNewStakes {
        uint256 totalStakedAmount = stake(_stakeOwner, _amount);

        emit AcceptedMigration(_stakeOwner, _amount, totalStakedAmount);

        // Note: we aren't concerned with reentrancy since:
        //   1. At this point, due to the CEI pattern, a reentrant notifier can't affect the effects of this method.
        //   2. The notifier is set and managed by the migration manager.
        stakeChange(_stakeOwner, _amount, true, totalStakedAmount);
    }

    /// @dev Migrates the stake of msg.sender from this staking contract to a new approved staking contract.
    /// @param _newStakingContract IMigratableStakingContract The new staking contract which supports stake migration.
    /// @param _amount uint256 The amount of tokens to migrate.
    function migrateStakedTokens(IMigratableStakingContract _newStakingContract, uint256 _amount) external
        onlyWhenStakesNotReleased {
        require(isApprovedStakingContract(_newStakingContract),
            "StakingContract::migrateStakedTokens - migration destination wasn't approved");
        require(_amount > 0, "StakingContract::migrateStakedTokens - amount must be greater than 0");

        address stakeOwner = msg.sender;
        Stake storage stakeData = stakes[stakeOwner];
        uint256 stakedAmount = stakeData.amount;

        require(stakedAmount > 0, "StakingContract::migrateStakedTokens - no staked tokens");
        require(_amount <= stakedAmount, "StakingContract::migrateStakedTokens - amount exceeds staked token balance");

        stakeData.amount = stakedAmount.sub(_amount);

        totalStakedTokens = totalStakedTokens.sub(_amount);

        require(_newStakingContract.getToken() == token,
            "StakingContract::migrateStakedTokens - staked tokens must be the same");
        require(token.approve(address(_newStakingContract), _amount),
            "StakingContract::migrateStakedTokens - couldn't approve transfer");

        emit MigratedStake(stakeOwner, _amount, stakeData.amount);

        _newStakingContract.acceptMigration(stakeOwner, _amount);

        // Note: we aren't concerned with reentrancy since:
        //   1. At this point, due to the CEI pattern, a reentrant notifier can't affect the effects of this method.
        //   2. The notifier is set and managed by the migration manager.
        stakeMigration(stakeOwner, _amount);
    }

    /// @dev Distributes staking rewards to a list of addresses by directly adding rewards to their stakes. This method
    /// assumes that the user has already approved at least the required amount using ERC20 approve. Since this is a
    /// convenience method, we aren't concerned about reaching block gas limit by using large lists. We assume that
    /// callers will be able to batch/paginate their requests properly.
    /// @param _totalAmount uint256 The total amount of rewards to distributes.
    /// @param _stakeOwners address[] The addresses of the stake owners.
    /// @param _amounts uint256[] The amounts of the rewards.
    function distributeRewards(uint256 _totalAmount, address[] calldata _stakeOwners, uint256[] calldata _amounts) external
        onlyWhenAcceptingNewStakes {
        require(_totalAmount > 0, "StakingContract::distributeRewards - total amount must be greater than 0");

        uint256 stakeOwnersLength = _stakeOwners.length;
        uint256 amountsLength = _amounts.length;

        require(stakeOwnersLength > 0 && amountsLength > 0,
            "StakingContract::distributeRewards - lists can't be empty");
        require(stakeOwnersLength == amountsLength,
            "StakingContract::distributeRewards - lists must be of the same size");

        // Transfer all the tokens to the smart contract and update the stake owners list accordingly.
        require(token.transferFrom(msg.sender, address(this), _totalAmount),
            "StakingContract::distributeRewards - insufficient allowance");

        bool[] memory signs = new bool[](amountsLength);
        uint256[] memory totalStakedAmounts = new uint256[](amountsLength);

        uint256 expectedTotalAmount = 0;
        for (uint i = 0; i < stakeOwnersLength; ++i) {
            address stakeOwner = _stakeOwners[i];
            uint256 amount = _amounts[i];

            require(stakeOwner != address(0), "StakingContract::distributeRewards - stake owner can't be 0");
            require(amount > 0, "StakingContract::distributeRewards - amount must be greater than 0");

            Stake storage stakeData = stakes[stakeOwner];
            stakeData.amount = stakeData.amount.add(amount);

            expectedTotalAmount = expectedTotalAmount.add(amount);

            uint256 totalStakedAmount = stakeData.amount;
            signs[i] = true;
            totalStakedAmounts[i] = totalStakedAmount;

            emit Staked(stakeOwner, amount, totalStakedAmount);
        }

        require(_totalAmount == expectedTotalAmount, "StakingContract::distributeRewards - incorrect total amount");

        totalStakedTokens = totalStakedTokens.add(_totalAmount);

        // Note: we aren't concerned with reentrancy since:
        //   1. At this point, due to the CEI pattern, a reentrant notifier can't affect the effects of this method.
        //   2. The notifier is set and managed by the migration manager.
        stakeChangeBatch(_stakeOwners, _amounts, signs, totalStakedAmounts);
    }

    /// @dev Returns the stake of the specified stake owner (excluding unstaked tokens).
    /// @param _stakeOwner address The address to check.
    /// @return uint256 The stake of the stake owner.
    function getStakeBalanceOf(address _stakeOwner) external view returns (uint256) {
        return stakes[_stakeOwner].amount;
    }

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

    /// @dev Returns the time that the cooldown period ends (or ended) and the amount of tokens to be released.
    /// @param _stakeOwner address The address to check.
    /// @return cooldownAmount uint256 The total tokens in cooldown.
    /// @return cooldownEndTime uint256 The time when the cooldown period ends (in seconds).
    function getUnstakeStatus(address _stakeOwner) external view returns (uint256 cooldownAmount,
        uint256 cooldownEndTime) {
        Stake memory stakeData = stakes[_stakeOwner];
        cooldownAmount = stakeData.cooldownAmount;
        cooldownEndTime = stakeData.cooldownEndTime;
    }

    /// @dev Returns the address of the underlying staked token.
    /// @return IERC20 The address of the token.
    function getToken() external view returns (IERC20) {
        return token;
    }

    /// @dev Requests the contract to stop accepting new staking requests.
    function stopAcceptingNewStakes() external onlyEmergencyManager onlyWhenAcceptingNewStakes {
        acceptingNewStakes = false;

        emit StoppedAcceptingNewStake();
    }

    /// @dev Requests the contract to release all stakes.
    function releaseAllStakes() external onlyEmergencyManager onlyWhenStakesNotReleased {
        releasingAllStakes = true;

        emit ReleasedAllStakes();
    }

    /// @dev Requests withdraw of released tokens for a list of addresses.
    /// @param _stakeOwners address[] The addresses of the stake owners.
    function withdrawReleasedStakes(address[] calldata _stakeOwners) external onlyWhenStakesReleased {
        uint256 stakeOwnersLength = _stakeOwners.length;
        uint256[] memory stakedAmountDiffs = new uint256[](stakeOwnersLength);
        bool[] memory signs = new bool[](stakeOwnersLength);
        uint256[] memory totalStakedAmounts = new uint256[](stakeOwnersLength);

        for (uint i = 0; i < stakeOwnersLength; ++i) {
            address stakeOwner = _stakeOwners[i];

            WithdrawResult memory res = withdraw(stakeOwner);
            stakedAmountDiffs[i] = res.stakedAmountDiff;
            signs[i] = false;
            totalStakedAmounts[i] = res.stakedAmount;

            emit Withdrew(stakeOwner, res.withdrawnAmount, res.stakedAmount);
        }

        // Note: we aren't concerned with reentrancy since:
        //   1. At this point, due to the CEI pattern, a reentrant notifier can't affect the effects of this method.
        //   2. The notifier is set and managed by the migration manager.
        stakeChangeBatch(_stakeOwners, stakedAmountDiffs, signs, totalStakedAmounts);
    }

    /// @dev Returns whether a specific staking contract was approved as a migration destination.
    /// @param _stakingContract IMigratableStakingContract The staking contract to look for.
    /// @return exists bool The approval status.
    function isApprovedStakingContract(IMigratableStakingContract _stakingContract) public view returns (bool exists) {
        (, exists) = findApprovedStakingContractIndex(_stakingContract);
    }

    /// @dev Returns whether stake change notification is enabled.
    function shouldNotifyStakeChange() view internal returns (bool) {
        return address(notifier) != address(0);
    }

    /// @dev Notifies of stake change events.
    /// @param _stakeOwner address The address of the subject stake owner.
    /// @param _amount int256 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) internal {
        if (!shouldNotifyStakeChange()) {
            return;
        }

        notifier.stakeChange(_stakeOwner, _amount, _sign, _updatedStake);
    }

    /// @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[] memory _stakeOwners, uint256[] memory _amounts, bool[] memory _signs,
        uint256[] memory _updatedStakes) internal {
        if (!shouldNotifyStakeChange()) {
            return;
        }

        notifier.stakeChangeBatch(_stakeOwners, _amounts, _signs, _updatedStakes);
    }

    /// @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) internal {
        if (!shouldNotifyStakeChange()) {
            return;
        }

        notifier.stakeMigration(_stakeOwner, _amount);
    }

    /// @dev Stakes amount of ORBS tokens on behalf of the specified stake owner.
    /// @param _stakeOwner address The specified stake owner.
    /// @param _amount uint256 The amount of tokens to stake.
    /// @return totalStakedAmount uint256 The total stake of the stake owner.
    function stake(address _stakeOwner, uint256 _amount) private returns (uint256 totalStakedAmount) {
        require(_stakeOwner != address(0), "StakingContract::stake - stake owner can't be 0");
        require(_amount > 0, "StakingContract::stake - amount must be greater than 0");

        Stake storage stakeData = stakes[_stakeOwner];
        stakeData.amount = stakeData.amount.add(_amount);

        totalStakedTokens = totalStakedTokens.add(_amount);

        totalStakedAmount = stakeData.amount;

        // Transfer the tokens to the smart contract and update the stake owners list accordingly.
        require(token.transferFrom(msg.sender, address(this), _amount),
            "StakingContract::stake - insufficient allowance");
    }

    /// @dev Requests to withdraw all of staked ORBS tokens back to the specified stake owner. Stake owners can withdraw
    /// their ORBS tokens only after previously unstaking them and after the cooldown period has passed (unless the
    /// contract was requested to release all stakes).
    /// @return res WithdrawResult The result of the withdraw operation.
    function withdraw(address _stakeOwner) private returns (WithdrawResult memory res) {
        require(_stakeOwner != address(0), "StakingContract::withdraw - stake owner can't be 0");

        Stake storage stakeData = stakes[_stakeOwner];
        res.stakedAmount = stakeData.amount;
        res.withdrawnAmount = stakeData.cooldownAmount;
        res.stakedAmountDiff = 0;

        if (!releasingAllStakes) {
            require(res.withdrawnAmount > 0, "StakingContract::withdraw - no unstaked tokens");
            require(stakeData.cooldownEndTime <= now, "StakingContract::withdraw - tokens are still in cooldown");
        } else {
            // If the contract was requested to release all stakes - allow to withdraw all staked and unstaked tokens.
            res.withdrawnAmount = res.withdrawnAmount.add(res.stakedAmount);
            res.stakedAmountDiff = res.stakedAmount;

            require(res.withdrawnAmount > 0, "StakingContract::withdraw - no staked or unstaked tokens");

            stakeData.amount = 0;

            totalStakedTokens = totalStakedTokens.sub(res.stakedAmount);

            res.stakedAmount = 0;
        }

        stakeData.cooldownAmount = 0;
        stakeData.cooldownEndTime = 0;

        require(token.transfer(_stakeOwner, res.withdrawnAmount),
            "StakingContract::withdraw - couldn't transfer stake");
    }

    /// @dev Returns an index of an existing approved staking contract.
    /// @param _stakingContract IMigratableStakingContract The staking contract to look for.
    /// @return index uint The index of the located staking contract (in the case that it was found).
    /// @return exists bool The search result.
    function findApprovedStakingContractIndex(IMigratableStakingContract _stakingContract) private view returns
        (uint index, bool exists) {
        uint length = approvedStakingContracts.length;
        for (index = 0; index < length; ++index) {
            if (approvedStakingContracts[index] == _stakingContract) {
                exists = true;
                return (index, exists);
            }
        }

        exists = false;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_cooldownPeriodInSec","type":"uint256"},{"internalType":"address","name":"_migrationManager","type":"address"},{"internalType":"address","name":"_emergencyManager","type":"address"},{"internalType":"contract IERC20","name":"_token","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalStakedAmount","type":"uint256"}],"name":"AcceptedMigration","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"emergencyManager","type":"address"}],"name":"EmergencyManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalStakedAmount","type":"uint256"}],"name":"MigratedStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IMigratableStakingContract","name":"stakingContract","type":"address"}],"name":"MigrationDestinationAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IMigratableStakingContract","name":"stakingContract","type":"address"}],"name":"MigrationDestinationRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"migrationManager","type":"address"}],"name":"MigrationManagerUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"ReleasedAllStakes","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalStakedAmount","type":"uint256"}],"name":"Restaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IStakeChangeNotifier","name":"notifier","type":"address"}],"name":"StakeChangeNotifierUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalStakedAmount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[],"name":"StoppedAcceptingNewStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalStakedAmount","type":"uint256"}],"name":"Unstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalStakedAmount","type":"uint256"}],"name":"Withdrew","type":"event"},{"constant":true,"inputs":[],"name":"MAX_APPROVED_STAKING_CONTRACTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"VERSION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_stakeOwner","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"acceptMigration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"acceptingNewStakes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IMigratableStakingContract","name":"_newStakingContract","type":"address"}],"name":"addMigrationDestination","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"approvedStakingContracts","outputs":[{"internalType":"contract IMigratableStakingContract","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"cooldownPeriodInSec","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_totalAmount","type":"uint256"},{"internalType":"address[]","name":"_stakeOwners","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"distributeRewards","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"emergencyManager","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_stakeOwner","type":"address"}],"name":"getStakeBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalStakedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_stakeOwner","type":"address"}],"name":"getUnstakeStatus","outputs":[{"internalType":"uint256","name":"cooldownAmount","type":"uint256"},{"internalType":"uint256","name":"cooldownEndTime","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"contract IMigratableStakingContract","name":"_stakingContract","type":"address"}],"name":"isApprovedStakingContract","outputs":[{"internalType":"bool","name":"exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IMigratableStakingContract","name":"_newStakingContract","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"migrateStakedTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"migrationManager","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"notifier","outputs":[{"internalType":"contract IStakeChangeNotifier","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"releaseAllStakes","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"releasingAllStakes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IMigratableStakingContract","name":"_stakingContract","type":"address"}],"name":"removeMigrationDestination","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"restake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newEmergencyManager","type":"address"}],"name":"setEmergencyManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newMigrationManager","type":"address"}],"name":"setMigrationManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IStakeChangeNotifier","name":"_newNotifier","type":"address"}],"name":"setStakeChangeNotifier","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"stopAcceptingNewStakes","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"_stakeOwners","type":"address[]"}],"name":"withdrawReleasedStakes","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063826cc8fc11610104578063bb82dd17116100a2578063df3f2f8a11610071578063df3f2f8a14610557578063e9aea8c814610583578063fa5b7c70146105a9578063ffa1ad74146105b1576101cf565b8063bb82dd17146104dd578063cced4f2014610503578063d0532d9114610529578063d2c18f591461054f576101cf565b80639db3c9ee116100de5780639db3c9ee146103fe578063a53acf6114610424578063a694fc3a14610450578063b5bab0151461046d576101cf565b8063826cc8fc146103c85780638cfc430e146103d057806396690c9e146103f6576101cf565b80633ccfd60b1161017157806351d185981161014b57806351d185981461034857806353a5b1bb146103505780636ef9abeb1461038f5780636fb974bc146103ac576101cf565b80633ccfd60b146103305780634b5d1f8b146103385780634f91440d14610340576101cf565b806319d6a88d116101ad57806319d6a88d1461022857806320fc287d146102f157806321df0da71461030b5780632e17de7814610313576101cf565b8063025cf89f146101d457806309276ea4146101fc578063187ac4cb14610220575b600080fd5b6101fa600480360360208110156101ea57600080fd5b50356001600160a01b03166105b9565b005b6102046106de565b604080516001600160a01b039092168252519081900360200190f35b6102046106ed565b6101fa6004803603606081101561023e57600080fd5b8135919081019060408101602082013564010000000081111561026057600080fd5b82018360208201111561027257600080fd5b8035906020019184602083028401116401000000008311171561029457600080fd5b9193909290916020810190356401000000008111156102b257600080fd5b8201836020820111156102c457600080fd5b803590602001918460208302840111640100000000831117156102e657600080fd5b5090925090506106fc565b6102f9610bb2565b60408051918252519081900360200190f35b610204610bb8565b6101fa6004803603602081101561032957600080fd5b5035610bc7565b6101fa610d58565b6102f9610de1565b6101fa610de6565b6102f9610f26565b6103766004803603602081101561036657600080fd5b50356001600160a01b0316610f2c565b6040805192835260208301919091528051918290030190f35b610204600480360360208110156103a557600080fd5b5035610f78565b6103b4610f9f565b604080519115158252519081900360200190f35b6101fa610faf565b6101fa600480360360208110156103e657600080fd5b50356001600160a01b03166110a9565b6101fa61124f565b6103b46004803603602081101561041457600080fd5b50356001600160a01b031661133a565b6101fa6004803603604081101561043a57600080fd5b506001600160a01b03813516906020013561134c565b6101fa6004803603602081101561046657600080fd5b5035611413565b6101fa6004803603602081101561048357600080fd5b81019060208101813564010000000081111561049e57600080fd5b8201836020820111156104b057600080fd5b803590602001918460208302840111640100000000831117156104d257600080fd5b5090925090506114d6565b6101fa600480360360208110156104f357600080fd5b50356001600160a01b03166116df565b6101fa6004803603602081101561051957600080fd5b50356001600160a01b03166118a9565b6101fa6004803603602081101561053f57600080fd5b50356001600160a01b031661198f565b610204611ab4565b6101fa6004803603604081101561056d57600080fd5b506001600160a01b038135169060200135611ac3565b6102f96004803603602081101561059957600080fd5b50356001600160a01b0316611eba565b6103b4611ed5565b6102f9611ee5565b6003546001600160a01b031633146106025760405162461bcd60e51b815260040180806020018281038252603481526020018061271d6034913960400191505060405180910390fd5b6001600160a01b0381166106475760405162461bcd60e51b815260040180806020018281038252603c815260200180612ee3603c913960400191505060405180910390fd5b6003546001600160a01b03828116911614156106945760405162461bcd60e51b81526004018080602001828103825260598152602001806130476059913960600191505060405180910390fd5b600380546001600160a01b0319166001600160a01b0383169081179091556040517fe06b7cc06400e2218f11a21ba24cb110fd587a695a09f36d42c4f7b21566937f90600090a250565b6006546001600160a01b031681565b6003546001600160a01b031681565b600754600160a01b900460ff16801561071f5750600754600160a81b900460ff16155b61075a5760405162461bcd60e51b8152600401808060200182810382526029815260200180612c576029913960400191505060405180910390fd5b600085116107995760405162461bcd60e51b8152600401808060200182810382526048815260200180612d786048913960600191505060405180910390fd5b828181158015906107aa5750600081115b6107e55760405162461bcd60e51b8152600401808060200182810382526039815260200180612f706039913960400191505060405180910390fd5b8082146108235760405162461bcd60e51b8152600401808060200182810382526043815260200180612dc06043913960600191505060405180910390fd5b600754604080516323b872dd60e01b8152336004820152306024820152604481018a905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b15801561087d57600080fd5b505af1158015610891573d6000803e3d6000fd5b505050506040513d60208110156108a757600080fd5b50516108e45760405162461bcd60e51b815260040180806020018281038252603b81526020018061288f603b913960400191505060405180910390fd5b606081604051908082528060200260200182016040528015610910578160200160208202803883390190505b50905060608260405190808252806020026020018201604052801561093f578160200160208202803883390190505b5090506000805b85811015610ae35760008a8a8381811061095c57fe5b905060200201356001600160a01b03169050600089898481811061097c57fe5b60200291909101359150506001600160a01b0382166109cc5760405162461bcd60e51b815260040180806020018281038252603b815260200180612785603b913960400191505060405180910390fd5b60008111610a0b5760405162461bcd60e51b8152600401808060200182810382526042815260200180612b756042913960600191505060405180910390fd5b6001600160a01b03821660009081526020819052604090208054610a35908363ffffffff611eea16565b8155610a47858363ffffffff611eea16565b94506000816000015490506001888681518110610a6057fe5b60200260200101901515908115158152505080878681518110610a7f57fe5b602002602001018181525050836001600160a01b03167f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee908483604051808381526020018281526020019250505060405180910390a250505050806001019050610946565b50808a14610b225760405162461bcd60e51b815260040180806020018281038252603b815260200180612e43603b913960400191505060405180910390fd5b600154610b35908b63ffffffff611eea16565b600155604080516020808b0282810182019093528a8252610ba6928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b918291850190849080828437600092019190915250889250879150611f449050565b50505050505050505050565b60025481565b6007546001600160a01b031690565b60008111610c065760405162461bcd60e51b8152600401808060200182810382526038815260200180612b3d6038913960400191505060405180910390fd5b33600081815260208190526040902080546001820154600283015482861115610c605760405162461bcd60e51b8152600401808060200182810382526044815260200180612d346044913960600191505060405180910390fd5b811580610c6c57504281115b610ca75760405162461bcd60e51b81526004018080602001828103825260558152602001806129726055913960600191505060405180910390fd5b610cb7838763ffffffff6120ed16565b8455610cc9828763ffffffff611eea16565b6001850155600254610ce290429063ffffffff611eea16565b6002850155600154610cfa908763ffffffff6120ed16565b6001558354604080518881526020810183905281516001600160a01b038916927f7fc4727e062e336010f2c282598ef5f14facb3de68cf8195c2f23e1454b2b74e928290030190a2610d4f868860008461214a565b50505050505050565b33610d616126fb565b610d6a826121d8565b8051602080830151604080519384529183015280519293506001600160a01b038516927fadec52fcd1408589179b85e44b434374db078b4eaf793e7d1a1bb0ae4ecfeee59281900390910190a26040810151610dc7575050610ddf565b610ddc8282604001516000846020015161214a565b50505b565b600a81565b600754600160a01b900460ff168015610e095750600754600160a81b900460ff16155b610e445760405162461bcd60e51b8152600401808060200182810382526029815260200180612c576029913960400191505060405180910390fd5b336000818152602081905260409020600181015480610e945760405162461bcd60e51b815260040180806020018281038252602d815260200180612a9b602d913960400191505060405180910390fd5b8154610ea6908263ffffffff611eea16565b825560006001808401829055600284019190915554610ecb908263ffffffff611eea16565b6001558154604080518381526020810183905281516001600160a01b038716927fa217c421e0e9357b7b1815d752952b142ddc0e23f9f14ecb8233f8f83d563c4d928290030190a2610f20848360018461214a565b50505050565b60015490565b600080610f376126fb565b5050506001600160a01b0316600090815260208181526040918290208251606081018452815481526001820154928101839052600290910154920182905291565b60058181548110610f8557fe5b6000918252602090912001546001600160a01b0316905081565b600754600160a01b900460ff1681565b6004546001600160a01b03163314610ff85760405162461bcd60e51b81526004018080602001828103825260348152602001806127516034913960400191505060405180910390fd5b600754600160a01b900460ff16801561101b5750600754600160a81b900460ff16155b6110565760405162461bcd60e51b8152600401808060200182810382526029815260200180612c576029913960400191505060405180910390fd5b600780547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517fbdbd7b3d2870b142b863f835ac06bf8aa59717f4295c2d0f4d9636fb4e5bb41890600090a1565b6003546001600160a01b031633146110f25760405162461bcd60e51b815260040180806020018281038252603481526020018061271d6034913960400191505060405180910390fd5b6001600160a01b0381166111375760405162461bcd60e51b8152600401808060200182810382526043815260200180612ac86043913960600191505060405180910390fd5b6000806111438361245f565b91509150806111835760405162461bcd60e51b815260040180806020018281038252604c815260200180612843604c913960600191505060405180910390fd5b60058054600019810190811061119557fe5b600091825260209091200154600580546001600160a01b0390921691849081106111bb57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060058054806111f457fe5b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b038516917f8510e225439ac2e1e619dffc86503855de99ded73d69499cadb36719ab7ac35491a2505050565b6004546001600160a01b031633146112985760405162461bcd60e51b81526004018080602001828103825260348152602001806127516034913960400191505060405180910390fd5b600754600160a81b900460ff16156112e15760405162461bcd60e51b8152600401808060200182810382526025815260200180612fd86025913960400191505060405180910390fd5b600780547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16600160a81b1790556040517f44562777dd33a811a41558cd3e94176385d383dfbef2e7daf1f568fb2a3a50b490600090a1565b60006113458261245f565b9392505050565b600754600160a01b900460ff16801561136f5750600754600160a81b900460ff16155b6113aa5760405162461bcd60e51b8152600401808060200182810382526029815260200180612c576029913960400191505060405180910390fd5b60006113b683836124c2565b9050826001600160a01b03167f81db9529cc03da6115de53b27832a9a0dde26bd573e99f76b23960f6be62b0c98383604051808381526020018281526020019250505060405180910390a261140e838360018461214a565b505050565b600754600160a01b900460ff1680156114365750600754600160a81b900460ff16155b6114715760405162461bcd60e51b8152600401808060200182810382526029815260200180612c576029913960400191505060405180910390fd5b33600061147e82846124c2565b9050816001600160a01b03167f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee908483604051808381526020018281526020019250505060405180910390a261140e828460018461214a565b600754600160a81b900460ff1661151e5760405162461bcd60e51b81526004018080602001828103825260298152602001806129496029913960400191505060405180910390fd5b604080518281526020808402820101909152819060609082801561154c578160200160208202803883390190505b50905060608260405190808252806020026020018201604052801561157b578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156115aa578160200160208202803883390190505b50905060005b848110156116955760008787838181106115c657fe5b905060200201356001600160a01b031690506115e06126fb565b6115e9826121d8565b905080604001518684815181106115fc57fe5b602002602001018181525050600085848151811061161657fe5b911515602092830291909101820152810151845185908590811061163657fe5b602090810291909101810191909152815182820151604080519283529282015281516001600160a01b038516927fadec52fcd1408589179b85e44b434374db078b4eaf793e7d1a1bb0ae4ecfeee5928290030190a250506001016115b0565b506116d7868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250879250869150859050611f44565b505050505050565b6003546001600160a01b031633146117285760405162461bcd60e51b815260040180806020018281038252603481526020018061271d6034913960400191505060405180910390fd5b6001600160a01b03811661176d5760405162461bcd60e51b8152600401808060200182810382526040815260200180612c806040913960400191505060405180910390fd5b600554600a6001820111156117b35760405162461bcd60e51b815260040180806020018281038252604b8152602001806127f8604b913960600191505060405180910390fd5b60005b8181101561182f57826001600160a01b0316600582815481106117d557fe5b6000918252602090912001546001600160a01b031614156118275760405162461bcd60e51b8152600401808060200182810382526051815260200180612f1f6051913960600191505060405180910390fd5b6001016117b6565b506005805460018101825560009182527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b0319166001600160a01b03851690811790915560405190917fc580726bc117ebe54aaf7f71f680c52208316d7dafdd4e165a4e402c032bbc6091a25050565b6003546001600160a01b031633146118f25760405162461bcd60e51b815260040180806020018281038252603481526020018061271d6034913960400191505060405180910390fd5b6006546001600160a01b038281169116141561193f5760405162461bcd60e51b815260040180806020018281038252605c815260200180612bb7605c913960600191505060405180910390fd5b600680546001600160a01b0319166001600160a01b0383811691909117918290556040519116907fbf46e3bdb5dd635a9a0d027fbb3c05e2b2f0e7c28a99fc6cd4bf5a7e3413d3be90600090a250565b6004546001600160a01b031633146119d85760405162461bcd60e51b81526004018080602001828103825260348152602001806127516034913960400191505060405180910390fd5b6001600160a01b038116611a1d5760405162461bcd60e51b815260040180806020018281038252603c815260200180612cc0603c913960400191505060405180910390fd5b6004546001600160a01b0382811691161415611a6a5760405162461bcd60e51b8152600401808060200182810382526059815260200180612a426059913960600191505060405180910390fd5b600480546001600160a01b0319166001600160a01b0383169081179091556040517fabe3ea374ec13aa47e312b4ed42fb5e9d47324c0d167dc4836aa048b8e5279ae90600090a250565b6004546001600160a01b031681565b600754600160a81b900460ff1615611b0c5760405162461bcd60e51b8152600401808060200182810382526025815260200180612fd86025913960400191505060405180910390fd5b611b158261133a565b611b505760405162461bcd60e51b815260040180806020018281038252604c8152602001806128fd604c913960600191505060405180910390fd5b60008111611b8f5760405162461bcd60e51b8152600401808060200182810382526044815260200180612c136044913960600191505060405180910390fd5b336000818152602081905260409020805480611bdc5760405162461bcd60e51b8152600401808060200182810382526037815260200180612eac6037913960400191505060405180910390fd5b80841115611c1b5760405162461bcd60e51b815260040180806020018281038252604a815260200180612ffd604a913960600191505060405180910390fd5b611c2b818563ffffffff6120ed16565b8255600154611c40908563ffffffff6120ed16565b600155600754604080517f21df0da700000000000000000000000000000000000000000000000000000000815290516001600160a01b03928316928816916321df0da7916004808301926020929190829003018186803b158015611ca357600080fd5b505afa158015611cb7573d6000803e3d6000fd5b505050506040513d6020811015611ccd57600080fd5b50516001600160a01b031614611d145760405162461bcd60e51b81526004018080602001828103825260458152602001806129fd6045913960600191505060405180910390fd5b600754604080517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890529151919092169163095ea7b39160448083019260209291908290030181600087803b158015611d8357600080fd5b505af1158015611d97573d6000803e3d6000fd5b505050506040513d6020811015611dad57600080fd5b5051611dea5760405162461bcd60e51b8152600401808060200182810382526040815260200180612e036040913960400191505060405180910390fd5b815460408051868152602081019290925280516001600160a01b038616927f9571cc7fab3ada3041abcbb4d26ead1cf5757f940f1096da3713584afc4b75cb92908290030190a2846001600160a01b031663a53acf6184866040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611e9157600080fd5b505af1158015611ea5573d6000803e3d6000fd5b50505050611eb38385612657565b5050505050565b6001600160a01b031660009081526020819052604090205490565b600754600160a81b900460ff1681565b600181565b600082820183811015611345576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b611f4c6126ea565b611f5557610f20565b6006546040517f90ef9d3f0000000000000000000000000000000000000000000000000000000081526080600482019081528651608483015286516001600160a01b03909316926390ef9d3f92889288928892889291829160248101916044820191606481019160a4909101906020808c01910280838360005b83811015611fe7578181015183820152602001611fcf565b50505050905001858103845288818151815260200191508051906020019060200280838360005b8381101561202657818101518382015260200161200e565b50505050905001858103835287818151815260200191508051906020019060200280838360005b8381101561206557818101518382015260200161204d565b50505050905001858103825286818151815260200191508051906020019060200280838360005b838110156120a457818101518382015260200161208c565b5050505090500198505050505050505050600060405180830381600087803b1580156120cf57600080fd5b505af11580156120e3573d6000803e3d6000fd5b5050505050505050565b600082821115612144576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6121526126ea565b61215b57610f20565b600654604080517f0e3b7c950000000000000000000000000000000000000000000000000000000081526001600160a01b0387811660048301526024820187905285151560448301526064820185905291519190921691630e3b7c9591608480830192600092919082900301818387803b1580156120cf57600080fd5b6121e06126fb565b6001600160a01b0382166122255760405162461bcd60e51b8152600401808060200182810382526032815260200180612b0b6032913960400191505060405180910390fd5b6001600160a01b03821660009081526020818152604080832080549285019290925260018201548452830191909152600754600160a81b900460ff166122ea5781516122a25760405162461bcd60e51b815260040180806020018281038252602e815260200180612e7e602e913960400191505060405180910390fd5b42816002015411156122e55760405162461bcd60e51b8152600401808060200182810382526038815260200180612cfc6038913960400191505060405180910390fd5b61236e565b602082015182516123009163ffffffff611eea16565b808352602083015160408401526123485760405162461bcd60e51b81526004018080602001828103825260388152602001806127c06038913960400191505060405180910390fd5b6000815560208201516001546123639163ffffffff6120ed16565b600155600060208301525b600060018201819055600282018190556007548351604080517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201939093529051919092169263a9059cbb92604480820193602093909283900390910190829087803b1580156123f257600080fd5b505af1158015612406573d6000803e3d6000fd5b505050506040513d602081101561241c57600080fd5b50516124595760405162461bcd60e51b81526004018080602001828103825260338152602001806128ca6033913960400191505060405180910390fd5b50919050565b60055460009081905b808310156124b757836001600160a01b03166005848154811061248757fe5b6000918252602090912001546001600160a01b031614156124ac5750600190506124bd565b826001019250612468565b60009150505b915091565b60006001600160a01b0383166125095760405162461bcd60e51b815260040180806020018281038252602f8152602001806130a0602f913960400191505060405180910390fd5b600082116125485760405162461bcd60e51b81526004018080602001828103825260368152602001806129c76036913960400191505060405180910390fd5b6001600160a01b03831660009081526020819052604090208054612572908463ffffffff611eea16565b8155600154612587908463ffffffff611eea16565b6001558054600754604080516323b872dd60e01b81523360048201523060248201526044810187905290519294506001600160a01b03909116916323b872dd916064808201926020929091908290030181600087803b1580156125e957600080fd5b505af11580156125fd573d6000803e3d6000fd5b505050506040513d602081101561261357600080fd5b50516126505760405162461bcd60e51b815260040180806020018281038252602f815260200180612fa9602f913960400191505060405180910390fd5b5092915050565b61265f6126ea565b61266857610ddc565b600654604080517fce257ab80000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152602482018590529151919092169163ce257ab891604480830192600092919082900301818387803b1580156126d657600080fd5b505af11580156116d7573d6000803e3d6000fd5b6006546001600160a01b0316151590565b6040518060600160405280600081526020016000815260200160008152509056fe5374616b696e67436f6e74726163743a2063616c6c6572206973206e6f7420746865206d6967726174696f6e206d616e616765725374616b696e67436f6e74726163743a2063616c6c6572206973206e6f742074686520656d657267656e6379206d616e616765725374616b696e67436f6e74726163743a3a6469737472696275746552657761726473202d207374616b65206f776e65722063616e277420626520305374616b696e67436f6e74726163743a3a7769746864726177202d206e6f207374616b6564206f7220756e7374616b656420746f6b656e735374616b696e67436f6e74726163743a3a6164644d6967726174696f6e44657374696e6174696f6e202d2063616e277420616464206d6f7265207374616b696e6720636f6e7472616374735374616b696e67436f6e74726163743a3a72656d6f76654d6967726174696f6e44657374696e6174696f6e202d207374616b696e6720636f6e747261637420646f65736e27742065786973745374616b696e67436f6e74726163743a3a6469737472696275746552657761726473202d20696e73756666696369656e7420616c6c6f77616e63655374616b696e67436f6e74726163743a3a7769746864726177202d20636f756c646e2774207472616e73666572207374616b655374616b696e67436f6e74726163743a3a6d6967726174655374616b6564546f6b656e73202d206d6967726174696f6e2064657374696e6174696f6e207761736e277420617070726f7665645374616b696e67436f6e74726163743a206e6f742072656c656173696e6720616c6c207374616b65735374616b696e67436f6e74726163743a3a756e7374616b65202d20756e61626c6520746f20756e7374616b65207768656e2074686572652061726520746f6b656e732070656e64696e67207769746864726177616c5374616b696e67436f6e74726163743a3a7374616b65202d20616d6f756e74206d7573742062652067726561746572207468616e20305374616b696e67436f6e74726163743a3a6d6967726174655374616b6564546f6b656e73202d207374616b656420746f6b656e73206d757374206265207468652073616d655374616b696e67436f6e74726163743a3a736574456d657267656e63794d616e61676572202d2061646472657373206d75737420626520646966666572656e74207468616e207468652063757272656e7420616464726573735374616b696e67436f6e74726163743a3a72657374616b65202d206e6f20756e7374616b656420746f6b656e735374616b696e67436f6e74726163743a3a72656d6f76654d6967726174696f6e44657374696e6174696f6e202d2061646472657373206d757374206e6f7420626520305374616b696e67436f6e74726163743a3a7769746864726177202d207374616b65206f776e65722063616e277420626520305374616b696e67436f6e74726163743a3a756e7374616b65202d20616d6f756e74206d7573742062652067726561746572207468616e20305374616b696e67436f6e74726163743a3a6469737472696275746552657761726473202d20616d6f756e74206d7573742062652067726561746572207468616e20305374616b696e67436f6e74726163743a3a7365745374616b654368616e67654e6f746966696572202d2061646472657373206d75737420626520646966666572656e74207468616e207468652063757272656e7420616464726573735374616b696e67436f6e74726163743a3a6d6967726174655374616b6564546f6b656e73202d20616d6f756e74206d7573742062652067726561746572207468616e20305374616b696e67436f6e74726163743a206e6f7420616363657074696e67206e6577207374616b65735374616b696e67436f6e74726163743a3a6164644d6967726174696f6e44657374696e6174696f6e202d2061646472657373206d757374206e6f7420626520305374616b696e67436f6e74726163743a3a736574456d657267656e63794d616e61676572202d2061646472657373206d757374206e6f7420626520305374616b696e67436f6e74726163743a3a7769746864726177202d20746f6b656e7320617265207374696c6c20696e20636f6f6c646f776e5374616b696e67436f6e74726163743a3a756e7374616b65202d2063616e277420756e7374616b65206d6f7265207468616e207468652063757272656e74207374616b655374616b696e67436f6e74726163743a3a6469737472696275746552657761726473202d20746f74616c20616d6f756e74206d7573742062652067726561746572207468616e20305374616b696e67436f6e74726163743a3a6469737472696275746552657761726473202d206c69737473206d757374206265206f66207468652073616d652073697a655374616b696e67436f6e74726163743a3a6d6967726174655374616b6564546f6b656e73202d20636f756c646e277420617070726f7665207472616e736665725374616b696e67436f6e74726163743a3a6469737472696275746552657761726473202d20696e636f727265637420746f74616c20616d6f756e745374616b696e67436f6e74726163743a3a7769746864726177202d206e6f20756e7374616b656420746f6b656e735374616b696e67436f6e74726163743a3a6d6967726174655374616b6564546f6b656e73202d206e6f207374616b656420746f6b656e735374616b696e67436f6e74726163743a3a7365744d6967726174696f6e4d616e61676572202d2061646472657373206d757374206e6f7420626520305374616b696e67436f6e74726163743a3a6164644d6967726174696f6e44657374696e6174696f6e202d2063616e2774206164642061206475706c6963617465207374616b696e6720636f6e74726163745374616b696e67436f6e74726163743a3a6469737472696275746552657761726473202d206c697374732063616e277420626520656d7074795374616b696e67436f6e74726163743a3a7374616b65202d20696e73756666696369656e7420616c6c6f77616e63655374616b696e67436f6e74726163743a2072656c656173696e6720616c6c207374616b65735374616b696e67436f6e74726163743a3a6d6967726174655374616b6564546f6b656e73202d20616d6f756e742065786365656473207374616b656420746f6b656e2062616c616e63655374616b696e67436f6e74726163743a3a7365744d6967726174696f6e4d616e61676572202d2061646472657373206d75737420626520646966666572656e74207468616e207468652063757272656e7420616464726573735374616b696e67436f6e74726163743a3a7374616b65202d207374616b65206f776e65722063616e27742062652030a265627a7a723158208532a51ebdf403ebe2950030aa735d5a9df31fb41ad5b47939d6a8e1d505a5ab64736f6c63430005100032

Deployed Bytecode Sourcemap

13307:29039:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;13307:29039:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18568:496;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;18568:496:0;-1:-1:-1;;;;;18568:496:0;;:::i;:::-;;14915:36;;;:::i;:::-;;;;-1:-1:-1;;;;;14915:36:0;;;;;;;;;;;;;;14406:31;;;:::i;30695:2411::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;30695:2411:0;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;30695:2411:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;30695:2411:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;30695:2411:0;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;30695:2411:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;30695:2411:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;30695:2411:0;;-1:-1:-1;30695:2411:0;-1:-1:-1;30695:2411:0;:::i;14281:34::-;;;:::i;:::-;;;;;;;;;;;;;;;;34480:82;;;:::i;23438:1692::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;23438:1692:0;;:::i;25418:725::-;;;:::i;13849:56::-;;;:::i;26234:987::-;;;:::i;33609:107::-;;;:::i;34059:297::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;34059:297:0;-1:-1:-1;;;;;34059:297:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;14755:60;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;14755:60:0;;:::i;15303:37::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;34646:180;;;:::i;21581:787::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;21581:787:0;-1:-1:-1;;;;;21581:787:0;;:::i;34893:165::-;;;:::i;36606:196::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;36606:196:0;-1:-1:-1;;;;;36606:196:0;;:::i;27527:574::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;27527:574:0;;;;;;;;:::i;22611:573::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;22611:573:0;;:::i;35216:1139::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;35216:1139:0;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;35216:1139:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;35216:1139:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;35216:1139:0;;-1:-1:-1;35216:1139:0;-1:-1:-1;35216:1139:0;:::i;20517:871::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;20517:871:0;-1:-1:-1;;;;;20517:871:0;;:::i;19973:348::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19973:348:0;-1:-1:-1;;;;;19973:348:0;;:::i;19216:496::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19216:496:0;-1:-1:-1;;;;;19216:496:0;;:::i;14562:31::-;;;:::i;28404:1636::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;28404:1636:0;;;;;;;;:::i;33317:132::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;33317:132:0;-1:-1:-1;;;;;33317:132:0;;:::i;15818:38::-;;;:::i;13724:32::-;;;:::i;18568:496::-;16403:16;;-1:-1:-1;;;;;16403:16:0;16389:10;:30;16381:95;;;;-1:-1:-1;;;16381:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;18676:34:0;;18668:107;;;;-1:-1:-1;;;18668:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18794:16;;-1:-1:-1;;;;;18794:40:0;;;:16;;:40;;18786:155;;;;-1:-1:-1;;;18786:155:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18954:16;:39;;-1:-1:-1;;;;;;18954:39:0;-1:-1:-1;;;;;18954:39:0;;;;;;;;19011:45;;;;-1:-1:-1;;19011:45:0;18568:496;:::o;14915:36::-;;;-1:-1:-1;;;;;14915:36:0;;:::o;14406:31::-;;;-1:-1:-1;;;;;14406:31:0;;:::o;30695:2411::-;16731:18;;-1:-1:-1;;;16731:18:0;;;;:41;;;;-1:-1:-1;16754:18:0;;-1:-1:-1;;;16754:18:0;;;;16753:19;16731:41;16723:95;;;;-1:-1:-1;;;16723:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30885:1;30870:12;:16;30862:101;;;;-1:-1:-1;;;30862:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31004:12;31058:8;31094:21;;;;;:42;;;31135:1;31119:13;:17;31094:42;31086:125;;;;-1:-1:-1;;;31086:125:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31251:13;31230:17;:34;31222:127;;;;-1:-1:-1;;;31222:127:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31474:5;;:59;;;-1:-1:-1;;;31474:59:0;;31493:10;31474:59;;;;31513:4;31474:59;;;;;;;;;;;;-1:-1:-1;;;;;31474:5:0;;;;:18;;:59;;;;;;;;;;;;;;;:5;;:59;;;5:2:-1;;;;30:1;27;20:12;5:2;31474:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;31474:59:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;31474:59:0;31466:144;;;;-1:-1:-1;;;31466:144:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31623:19;31656:13;31645:25;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;31645:25:0;;31623:47;;31681:35;31733:13;31719:28;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;31719:28:0;-1:-1:-1;31681:66:0;-1:-1:-1;31760:27:0;;31802:775;31823:17;31819:1;:21;31802:775;;;31862:18;31883:12;;31896:1;31883:15;;;;;;;;;;;;;-1:-1:-1;;;;;31883:15:0;31862:36;;31913:14;31930:8;;31939:1;31930:11;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;31966:24:0;;31958:96;;;;-1:-1:-1;;;31958:96:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32086:1;32077:6;:10;32069:89;;;;-1:-1:-1;;;32069:89:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;32201:18:0;;32175:23;32201:18;;;;;;;;;;32253:16;;:28;;32274:6;32253:28;:20;:28;:::i;:::-;32234:47;;32320:31;:19;32344:6;32320:31;:23;:31;:::i;:::-;32298:53;;32368:25;32396:9;:16;;;32368:44;;32438:4;32427:5;32433:1;32427:8;;;;;;;;;;;;;:15;;;;;;;;;;;32481:17;32457:18;32476:1;32457:21;;;;;;;;;;;;;:41;;;;;32527:10;-1:-1:-1;;;;;32520:45:0;;32539:6;32547:17;32520:45;;;;;;;;;;;;;;;;;;;;;;;;31802:775;;;;31842:3;;;;;31802:775;;;;32613:19;32597:12;:35;32589:107;;;;-1:-1:-1;;;32589:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32729:17;;:35;;32751:12;32729:35;:21;:35;:::i;:::-;32709:17;:55;33031:67;;;;;;;;;;;;;;;;;;;;33048:12;;;;;;33031:67;;;33048:12;;33031:67;33048:12;33031:67;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;33031:67:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33062:8:0;;-1:-1:-1;33062:8:0;;;;33031:67;;;33062:8;;33031:67;33062:8;33031:67;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;33072:5:0;;-1:-1:-1;33079:18:0;;-1:-1:-1;33031:16:0;;-1:-1:-1;33031:67:0:i;:::-;16831:1;;;;;30695:2411;;;;;:::o;14281:34::-;;;;:::o;34480:82::-;34549:5;;-1:-1:-1;;;;;34549:5:0;34480:82;:::o;23438:1692::-;23510:1;23500:7;:11;23492:80;;;;-1:-1:-1;;;23492:80:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23606:10;23585:18;23653;;;;;;;;;;23705:16;;23757:24;;;;23818:25;;;;23864:23;;;;23856:104;;;;-1:-1:-1;;;23856:104:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24123:19;;;:44;;;24164:3;24146:15;:21;24123:44;24115:155;;;;-1:-1:-1;;;24115:155:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24454:25;:12;24471:7;24454:25;:16;:25;:::i;:::-;24435:44;;24517:27;:14;24536:7;24517:27;:18;:27;:::i;:::-;24490:24;;;:54;24591:19;;24583:28;;:3;;:28;:7;:28;:::i;:::-;24555:25;;;:56;24644:17;;:30;;24666:7;24644:30;:21;:30;:::i;:::-;24624:17;:50;24715:16;;24749:48;;;;;;;;;;;;;;-1:-1:-1;;;;;24749:48:0;;;;;;;;;;;25064:58;25076:10;25088:7;25097:5;25104:17;25064:11;:58::i;:::-;23438:1692;;;;;;;:::o;25418:725::-;25479:10;25502:25;;:::i;:::-;25530:20;25539:10;25530:8;:20::i;:::-;25589:19;;25610:16;;;;;25568:59;;;;;;;;;;;;25502:48;;-1:-1:-1;;;;;;25568:59:0;;;;;;;;;;;;;25739:20;;;;25735:64;;25781:7;;;;25735:64;26065:70;26077:10;26089:3;:20;;;26111:5;26118:3;:16;;;26065:11;:70::i;:::-;25418:725;;;:::o;13849:56::-;13903:2;13849:56;:::o;26234:987::-;16731:18;;-1:-1:-1;;;16731:18:0;;;;:41;;;;-1:-1:-1;16754:18:0;;-1:-1:-1;;;16754:18:0;;;;16753:19;16731:41;16723:95;;;;-1:-1:-1;;;16723:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26321:10;26300:18;26368;;;;;;;;;;26422:24;;;;26467:18;26459:76;;;;-1:-1:-1;;;26459:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26567:16;;:36;;26588:14;26567:36;:20;:36;:::i;:::-;26548:55;;:16;26614:24;;;;:28;;;26653:25;;;:29;;;;26715:17;:37;;26737:14;26715:37;:21;:37;:::i;:::-;26695:17;:57;26793:16;;26827:55;;;;;;;;;;;;;;-1:-1:-1;;;;;26827:55:0;;;;;;;;;;;27149:64;27161:10;27173:14;27189:4;27195:17;27149:11;:64::i;:::-;16831:1;;;;26234:987::o;33609:107::-;33691:17;;33609:107;:::o;34059:297::-;34129:22;34162:23;34198:22;;:::i;:::-;-1:-1:-1;;;;;;;;34223:19:0;:6;:19;;;;;;;;;;;;34198:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34059:297::o;14755:60::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;14755:60:0;;-1:-1:-1;14755:60:0;:::o;15303:37::-;;;-1:-1:-1;;;15303:37:0;;;;;:::o;34646:180::-;16571:16;;-1:-1:-1;;;;;16571:16:0;16557:10;:30;16549:95;;;;-1:-1:-1;;;16549:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16731:18;;-1:-1:-1;;;16731:18:0;;;;:41;;;;-1:-1:-1;16754:18:0;;-1:-1:-1;;;16754:18:0;;;;16753:19;16731:41;16723:95;;;;-1:-1:-1;;;16723:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34748:18;:26;;;;;;34792;;;;34769:5;;34792:26;34646:180::o;21581:787::-;16403:16;;-1:-1:-1;;;;;16403:16:0;16389:10;:30;16381:95;;;;-1:-1:-1;;;16381:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;21711:39:0;;21703:132;;;;-1:-1:-1;;;21703:132:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21882:6;21890:11;21905:50;21938:16;21905:32;:50::i;:::-;21881:74;;;;21974:6;21966:95;;;;-1:-1:-1;;;21966:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22195:24;22220:31;;-1:-1:-1;;22220:35:0;;;22195:61;;;;;;;;;;;;;;;;22165:24;:27;;-1:-1:-1;;;;;22195:61:0;;;;22190:1;;22165:27;;;;;;;;;;;;;;:91;;;;;-1:-1:-1;;;;;22165:91:0;;;;;-1:-1:-1;;;;;22165:91:0;;;;;;22267:24;:30;;;;;;;;;;;;;;;;-1:-1:-1;;22267:30:0;;;;;-1:-1:-1;;;;;;22267:30:0;;;;;;;;;22315:45;;-1:-1:-1;;;;;22315:45:0;;;;;;16489:1;;21581:787;:::o;34893:165::-;16571:16;;-1:-1:-1;;;;;16571:16:0;16557:10;:30;16549:95;;;;-1:-1:-1;;;16549:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17052:18;;-1:-1:-1;;;17052:18:0;;;;17051:19;17043:69;;;;-1:-1:-1;;;17043:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34988:18;:25;;;;-1:-1:-1;;;34988:25:0;;;35031:19;;;;34988:25;;35031:19;34893:165::o;36606:196::-;36707:11;36744:50;36777:16;36744:32;:50::i;:::-;36731:63;36606:196;-1:-1:-1;;;36606:196:0:o;27527:574::-;16731:18;;-1:-1:-1;;;16731:18:0;;;;:41;;;;-1:-1:-1;16754:18:0;;-1:-1:-1;;;16754:18:0;;;;16753:19;16731:41;16723:95;;;;-1:-1:-1;;;16723:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27637:25;27665:27;27671:11;27684:7;27665:5;:27::i;:::-;27637:55;;27728:11;-1:-1:-1;;;;;27710:58:0;;27741:7;27750:17;27710:58;;;;;;;;;;;;;;;;;;;;;;;;28035;28047:11;28060:7;28069:4;28075:17;28035:11;:58::i;:::-;16831:1;27527:574;;:::o;22611:573::-;16731:18;;-1:-1:-1;;;16731:18:0;;;;:41;;;;-1:-1:-1;16754:18:0;;-1:-1:-1;;;16754:18:0;;;;16753:19;16731:41;16723:95;;;;-1:-1:-1;;;16723:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22711:10;22690:18;22762:26;22711:10;22780:7;22762:5;:26::i;:::-;22734:54;;22813:10;-1:-1:-1;;;;;22806:46:0;;22825:7;22834:17;22806:46;;;;;;;;;;;;;;;;;;;;;;;;23119:57;23131:10;23143:7;23152:4;23158:17;23119:11;:57::i;35216:1139::-;16901:18;;-1:-1:-1;;;16901:18:0;;;;16893:72;;;;-1:-1:-1;;;16893:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35419:32;;;;;;;;;;;;;;;;35352:12;;35382:34;;35352:12;35419:32;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;35419:32:0;;35382:69;;35462:19;35495:17;35484:29;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;35484:29:0;;35462:51;;35524:35;35576:17;35562:32;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;35562:32:0;-1:-1:-1;35524:70:0;-1:-1:-1;35612:6:0;35607:398;35628:17;35624:1;:21;35607:398;;;35667:18;35688:12;;35701:1;35688:15;;;;;;;;;;;;;-1:-1:-1;;;;;35688:15:0;35667:36;;35720:25;;:::i;:::-;35748:20;35757:10;35748:8;:20::i;:::-;35720:48;;35806:3;:20;;;35783:17;35801:1;35783:20;;;;;;;;;;;;;:43;;;;;35852:5;35841;35847:1;35841:8;;;;;;;;:16;;;:8;;;;;;;;;;:16;35896;;;35872:21;;:18;;35891:1;;35872:21;;;;;;;;;;;;;;;;:40;;;;35955:19;;35976:16;;;;35934:59;;;;;;;;;;;;-1:-1:-1;;;;;35934:59:0;;;;;;;;;;;-1:-1:-1;;35647:3:0;;35607:398;;;;36271:76;36288:12;;36271:76;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;36302:17:0;;-1:-1:-1;36321:5:0;;-1:-1:-1;36328:18:0;;-1:-1:-1;36271:16:0;:76::i;:::-;16978:1;;;;35216:1139;;:::o;20517:871::-;16403:16;;-1:-1:-1;;;;;16403:16:0;16389:10;:30;16381:95;;;;-1:-1:-1;;;16381:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;20647:42:0;;20639:132;;;;-1:-1:-1;;;20639:132:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20798:24;:31;13903:2;20857:1;20848:10;;:44;;20840:145;;;;-1:-1:-1;;;20840:145:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21037:6;21032:222;21053:6;21049:1;:10;21032:222;;;21120:19;-1:-1:-1;;;;;21089:50:0;:24;21114:1;21089:27;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;21089:27:0;:50;;21081:161;;;;-1:-1:-1;;;21081:161:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21061:3;;21032:222;;;-1:-1:-1;21266:24:0;27:10:-1;;39:1;23:18;;45:23;;-1:-1;21266:50:0;;;;;;;-1:-1:-1;;;;;;21266:50:0;-1:-1:-1;;;;;21266:50:0;;;;;;;;21334:46;;21266:50;;21334:46;;;16489:1;20517:871;:::o;19973:348::-;16403:16;;-1:-1:-1;;;;;16403:16:0;16389:10;:30;16381:95;;;;-1:-1:-1;;;16381:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20089:8;;-1:-1:-1;;;;;20089:24:0;;;:8;;:24;;20081:142;;;;-1:-1:-1;;;20081:142:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20236:8;:23;;-1:-1:-1;;;;;;20236:23:0;-1:-1:-1;;;;;20236:23:0;;;;;;;;;;;20277:36;;20304:8;;;20277:36;;-1:-1:-1;;20277:36:0;19973:348;:::o;19216:496::-;16571:16;;-1:-1:-1;;;;;16571:16:0;16557:10;:30;16549:95;;;;-1:-1:-1;;;16549:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19324:34:0;;19316:107;;;;-1:-1:-1;;;19316:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19442:16;;-1:-1:-1;;;;;19442:40:0;;;:16;;:40;;19434:155;;;;-1:-1:-1;;;19434:155:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19602:16;:39;;-1:-1:-1;;;;;;19602:39:0;-1:-1:-1;;;;;19602:39:0;;;;;;;;19659:45;;;;-1:-1:-1;;19659:45:0;19216:496;:::o;14562:31::-;;;-1:-1:-1;;;;;14562:31:0;;:::o;28404:1636::-;17052:18;;-1:-1:-1;;;17052:18:0;;;;17051:19;17043:69;;;;-1:-1:-1;;;17043:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28561:46;28587:19;28561:25;:46::i;:::-;28553:148;;;;-1:-1:-1;;;28553:148:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28730:1;28720:7;:11;28712:92;;;;-1:-1:-1;;;28712:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28838:10;28817:18;28885;;;;;;;;;;28937:16;;28974;28966:84;;;;-1:-1:-1;;;28966:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29080:12;29069:7;:23;;29061:110;;;;-1:-1:-1;;;29061:110:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29203:25;:12;29220:7;29203:25;:16;:25;:::i;:::-;29184:44;;29261:17;;:30;;29283:7;29261:30;:21;:30;:::i;:::-;29241:17;:50;29346:5;;29312:30;;;;;;;;-1:-1:-1;;;;;29346:5:0;;;;29312:28;;;;;:30;;;;;;;;;;;;;;:28;:30;;;5:2:-1;;;;30:1;27;20:12;5:2;29312:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29312:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29312:30:0;-1:-1:-1;;;;;29312:39:0;;29304:134;;;;-1:-1:-1;;;29304:134:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29457:5;;:52;;;;;;-1:-1:-1;;;;;29457:52:0;;;;;;;;;;;;;;;:5;;;;;:13;;:52;;;;;;;;;;;;;;:5;;:52;;;5:2:-1;;;;30:1;27;20:12;5:2;29457:52:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29457:52:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29457:52:0;29449:142;;;;-1:-1:-1;;;29449:142:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29644:16;;29609:52;;;;;;;;;;;;;;;-1:-1:-1;;;;;29609:52:0;;;;;;;;;;;;29674:19;-1:-1:-1;;;;;29674:35:0;;29710:10;29722:7;29674:56;;;;;;;;;;;;;-1:-1:-1;;;;;29674:56:0;-1:-1:-1;;;;;29674:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;29674:56:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29674:56:0;;;;29997:35;30012:10;30024:7;29997:14;:35::i;:::-;17125:1;;;28404:1636;;:::o;33317:132::-;-1:-1:-1;;;;;33415:19:0;33388:7;33415:19;;;;;;;;;;:26;;33317:132::o;15818:38::-;;;-1:-1:-1;;;15818:38:0;;;;;:::o;13724:32::-;13755:1;13724:32;:::o;1393:181::-;1451:7;1483:5;;;1507:6;;;;1499:46;;;;;-1:-1:-1;;;1499:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;38008:326;38181:25;:23;:25::i;:::-;38176:65;;38223:7;;38176:65;38253:8;;:73;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;38253:8:0;;;;:25;;38279:12;;38293:8;;38303:6;;38311:14;;38253:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:8;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;38253:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;38253:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;38253:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;38253:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;38253:73:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38253:73:0;;;;38008:326;;;;:::o;1849:184::-;1907:7;1940:1;1935;:6;;1927:49;;;;;-1:-1:-1;;;1927:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1999:5:0;;;1849:184::o;37361:263::-;37480:25;:23;:25::i;:::-;37475:65;;37522:7;;37475:65;37552:8;;:64;;;;;;-1:-1:-1;;;;;37552:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:8;;;;;:20;;:64;;;;;:8;;:64;;;;;;;:8;;:64;;;5:2:-1;;;;30:1;27;20:12;40164:1396:0;40220:25;;:::i;:::-;-1:-1:-1;;;;;40266:25:0;;40258:88;;;;-1:-1:-1;;;40258:88:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;40385:19:0;;40359:23;40385:19;;;;;;;;;;;40434:16;;40415;;;:35;;;;40483:24;;;;40461:46;;40518:20;;:24;;;;40560:18;;-1:-1:-1;;;40560:18:0;;;;40555:779;;40603:19;;40595:82;;;;-1:-1:-1;;;40595:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40729:3;40700:9;:25;;;:32;;40692:101;;;;-1:-1:-1;;;40692:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40555:779;;;40992:16;;;;40968:19;;:41;;;:23;:41;:::i;:::-;40946:63;;;41047:16;;;;41024:20;;;:39;41080:92;;;;-1:-1:-1;;;41080:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41208:1;41189:20;;41268:16;;;;41246:17;;:39;;;:21;:39;:::i;:::-;41226:17;:59;41321:1;41302:16;;;:20;40555:779;41373:1;41346:24;;;:28;;;41385:25;;;:29;;;41435:5;;41463:19;;41435:48;;;;;;-1:-1:-1;;;;;41435:48:0;;;;;;;;;;;;;;;;:5;;;;;:14;;:48;;;;;;;;;;;;;;;;;;:5;:48;;;5:2:-1;;;;30:1;27;20:12;5:2;41435:48:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41435:48:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41435:48:0;41427:125;;;;-1:-1:-1;;;41427:125:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40164:1396;;;;:::o;41886:457::-;42054:24;:31;42004:10;;;;42096:213;42120:6;42112:5;:14;42096:213;;;42191:16;-1:-1:-1;;;;;42156:51:0;:24;42181:5;42156:31;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;42156:31:0;:51;42152:146;;;-1:-1:-1;42237:4:0;;-1:-1:-1;42260:22:0;;42152:146;42128:7;;;;;42096:213;;;42330:5;42321:14;;41886:457;;;;;:::o;39028:759::-;39098:25;-1:-1:-1;;;;;39144:25:0;;39136:85;;;;-1:-1:-1;;;39136:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39250:1;39240:7;:11;39232:78;;;;-1:-1:-1;;;39232:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;39349:19:0;;39323:23;39349:19;;;;;;;;;;39398:16;;:29;;39419:7;39398:29;:20;:29;:::i;:::-;39379:48;;39460:17;;:30;;39482:7;39460:30;:21;:30;:::i;:::-;39440:17;:50;39523:16;;39660:5;;:54;;;-1:-1:-1;;;39660:54:0;;39679:10;39660:54;;;;39699:4;39660:54;;;;;;;;;;;;39523:16;;-1:-1:-1;;;;;;39660:5:0;;;;:18;;:54;;;;;;;;;;;;;;;39523:16;39660:5;:54;;;5:2:-1;;;;30:1;27;20:12;5:2;39660:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;39660:54:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;39660:54:0;39652:127;;;;-1:-1:-1;;;39652:127:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39028:759;;;;;:::o;38520:212::-;38607:25;:23;:25::i;:::-;38602:65;;38649:7;;38602:65;38679:8;;:45;;;;;;-1:-1:-1;;;;;38679:45:0;;;;;;;;;;;;;;;:8;;;;;:23;;:45;;;;;:8;;:45;;;;;;;:8;;:45;;;5:2:-1;;;;30:1;27;20:12;5:2;38679:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;36878:121:0;36968:8;;-1:-1:-1;;;;;36968:8:0;36960:31;;36878:121;:::o;13307:29039::-;;;;;;;;;;;;;;;;;;;;;;;;:::o

Swarm Source

bzzr://8532a51ebdf403ebe2950030aa735d5a9df31fb41ad5b47939d6a8e1d505a5ab

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.