ETH Price: $1,878.15 (-12.40%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

More Info

Private Name Tags

TokenTracker

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Transfer152600212022-08-02 0:57:261283 days ago1659401846IN
0x47EbaB13...70D130b50
0.0005 ETH0.0002734811.35422529
Transfer152600172022-08-02 0:56:261283 days ago1659401786IN
0x47EbaB13...70D130b50
0.001 ETH0.000198199.43806525

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Lido

Compiler Version
v0.4.24+commit.e67f0147

Optimization Enabled:
Yes with 200 runs

Other Settings:
constantinople EvmVersion
File 1 of 35 : Lido.sol
// SPDX-FileCopyrightText: 2020 Lido <[email protected]>

// SPDX-License-Identifier: GPL-3.0

/* See contracts/COMPILERS.md */
pragma solidity 0.4.24;

import "@aragon/os/contracts/apps/AragonApp.sol";
import "@aragon/os/contracts/lib/math/SafeMath.sol";
import "@aragon/os/contracts/lib/math/SafeMath64.sol";
import "solidity-bytes-utils/contracts/BytesLib.sol";

import "./interfaces/ILido.sol";
import "./interfaces/INodeOperatorsRegistry.sol";
import "./interfaces/IDepositContract.sol";
import "./interfaces/ILidoExecutionLayerRewardsVault.sol";

import "./StETH.sol";

import "./lib/StakeLimitUtils.sol";


interface IERC721 {
    /// @notice Transfer ownership of an NFT
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
}


/**
* @title Liquid staking pool implementation
*
* Lido is an Ethereum 2.0 liquid staking protocol solving the problem of frozen staked Ethers
* until transfers become available in Ethereum 2.0.
* Whitepaper: https://lido.fi/static/Lido:Ethereum-Liquid-Staking.pdf
*
* NOTE: the code below assumes moderate amount of node operators, e.g. up to 200.
*
* Since balances of all token holders change when the amount of total pooled Ether
* changes, this token cannot fully implement ERC20 standard: it only emits `Transfer`
* events upon explicit transfer between holders. In contrast, when Lido oracle reports
* rewards, no Transfer events are generated: doing so would require emitting an event
* for each token holder and thus running an unbounded loop.
*
* At the moment withdrawals are not possible in the beacon chain and there's no workaround.
* Pool will be upgraded to an actual implementation when withdrawals are enabled
* (Phase 1.5 or 2 of Eth2 launch, likely late 2022 or 2023).
*/
contract Lido is ILido, StETH, AragonApp {
    using SafeMath for uint256;
    using UnstructuredStorage for bytes32;
    using StakeLimitUnstructuredStorage for bytes32;
    using StakeLimitUtils for StakeLimitState.Data;

    /// ACL
    bytes32 constant public PAUSE_ROLE = keccak256("PAUSE_ROLE");
    bytes32 constant public RESUME_ROLE = keccak256("RESUME_ROLE");
    bytes32 constant public STAKING_PAUSE_ROLE = keccak256("STAKING_PAUSE_ROLE");
    bytes32 constant public STAKING_CONTROL_ROLE = keccak256("STAKING_CONTROL_ROLE");
    bytes32 constant public MANAGE_FEE = keccak256("MANAGE_FEE");
    bytes32 constant public MANAGE_WITHDRAWAL_KEY = keccak256("MANAGE_WITHDRAWAL_KEY");
    bytes32 constant public MANAGE_PROTOCOL_CONTRACTS_ROLE = keccak256("MANAGE_PROTOCOL_CONTRACTS_ROLE");
    bytes32 constant public BURN_ROLE = keccak256("BURN_ROLE");
    bytes32 constant public DEPOSIT_ROLE = keccak256("DEPOSIT_ROLE");
    bytes32 constant public SET_EL_REWARDS_VAULT_ROLE = keccak256("SET_EL_REWARDS_VAULT_ROLE");
    bytes32 constant public SET_EL_REWARDS_WITHDRAWAL_LIMIT_ROLE = keccak256(
        "SET_EL_REWARDS_WITHDRAWAL_LIMIT_ROLE"
    );

    uint256 constant public PUBKEY_LENGTH = 48;
    uint256 constant public WITHDRAWAL_CREDENTIALS_LENGTH = 32;
    uint256 constant public SIGNATURE_LENGTH = 96;

    uint256 constant public DEPOSIT_SIZE = 32 ether;

    uint256 internal constant DEPOSIT_AMOUNT_UNIT = 1000000000 wei;
    uint256 internal constant TOTAL_BASIS_POINTS = 10000;

    /// @dev default value for maximum number of Ethereum 2.0 validators registered in a single depositBufferedEther call
    uint256 internal constant DEFAULT_MAX_DEPOSITS_PER_CALL = 150;

    bytes32 internal constant FEE_POSITION = keccak256("lido.Lido.fee");
    bytes32 internal constant TREASURY_FEE_POSITION = keccak256("lido.Lido.treasuryFee");
    bytes32 internal constant INSURANCE_FEE_POSITION = keccak256("lido.Lido.insuranceFee");
    bytes32 internal constant NODE_OPERATORS_FEE_POSITION = keccak256("lido.Lido.nodeOperatorsFee");

    bytes32 internal constant DEPOSIT_CONTRACT_POSITION = keccak256("lido.Lido.depositContract");
    bytes32 internal constant ORACLE_POSITION = keccak256("lido.Lido.oracle");
    bytes32 internal constant NODE_OPERATORS_REGISTRY_POSITION = keccak256("lido.Lido.nodeOperatorsRegistry");
    bytes32 internal constant TREASURY_POSITION = keccak256("lido.Lido.treasury");
    bytes32 internal constant INSURANCE_FUND_POSITION = keccak256("lido.Lido.insuranceFund");
    bytes32 internal constant EL_REWARDS_VAULT_POSITION = keccak256("lido.Lido.executionLayerRewardsVault");

    /// @dev storage slot position of the staking rate limit structure
    bytes32 internal constant STAKING_STATE_POSITION = keccak256("lido.Lido.stakeLimit");
    /// @dev amount of Ether (on the current Ethereum side) buffered on this smart contract balance
    bytes32 internal constant BUFFERED_ETHER_POSITION = keccak256("lido.Lido.bufferedEther");
    /// @dev number of deposited validators (incrementing counter of deposit operations).
    bytes32 internal constant DEPOSITED_VALIDATORS_POSITION = keccak256("lido.Lido.depositedValidators");
    /// @dev total amount of Beacon-side Ether (sum of all the balances of Lido validators)
    bytes32 internal constant BEACON_BALANCE_POSITION = keccak256("lido.Lido.beaconBalance");
    /// @dev number of Lido's validators available in the Beacon state
    bytes32 internal constant BEACON_VALIDATORS_POSITION = keccak256("lido.Lido.beaconValidators");

    /// @dev percent in basis points of total pooled ether allowed to withdraw from LidoExecutionLayerRewardsVault per LidoOracle report
    bytes32 internal constant EL_REWARDS_WITHDRAWAL_LIMIT_POSITION = keccak256("lido.Lido.ELRewardsWithdrawalLimit");

    /// @dev Just a counter of total amount of execution layer rewards received by Lido contract
    /// Not used in the logic
    bytes32 internal constant TOTAL_EL_REWARDS_COLLECTED_POSITION = keccak256("lido.Lido.totalELRewardsCollected");

    /// @dev Credentials which allows the DAO to withdraw Ether on the 2.0 side
    bytes32 internal constant WITHDRAWAL_CREDENTIALS_POSITION = keccak256("lido.Lido.withdrawalCredentials");

    /**
    * @dev As AragonApp, Lido contract must be initialized with following variables:
    * @param _depositContract official ETH2 Deposit contract
    * @param _oracle oracle contract
    * @param _operators instance of Node Operators Registry
    * @param _treasury treasury contract
    * @param _insuranceFund insurance fund contract
    * NB: by default, staking and the whole Lido pool are in paused state
    */
    function initialize(
        IDepositContract _depositContract,
        address _oracle,
        INodeOperatorsRegistry _operators,
        address _treasury,
        address _insuranceFund
    )
        public onlyInit
    {
        NODE_OPERATORS_REGISTRY_POSITION.setStorageAddress(address(_operators));
        DEPOSIT_CONTRACT_POSITION.setStorageAddress(address(_depositContract));

        _setProtocolContracts(_oracle, _treasury, _insuranceFund);

        initialized();
    }

    /**
    * @notice Stops accepting new Ether to the protocol
    *
    * @dev While accepting new Ether is stopped, calls to the `submit` function,
    * as well as to the default payable function, will revert.
    *
    * Emits `StakingPaused` event.
    */
    function pauseStaking() external {
        _auth(STAKING_PAUSE_ROLE);

        _pauseStaking();
    }

    /**
    * @notice Resumes accepting new Ether to the protocol (if `pauseStaking` was called previously)
    * NB: Staking could be rate-limited by imposing a limit on the stake amount
    * at each moment in time, see `setStakingLimit()` and `removeStakingLimit()`
    *
    * @dev Preserves staking limit if it was set previously
    *
    * Emits `StakingResumed` event
    */
    function resumeStaking() external {
        _auth(STAKING_CONTROL_ROLE);

        _resumeStaking();
    }

    /**
    * @notice Sets the staking rate limit
    *
    * ▲ Stake limit
    * │.....  .....   ........ ...            ....     ... Stake limit = max
    * │      .       .        .   .   .      .    . . .
    * │     .       .              . .  . . .      . .
    * │            .                .  . . .
    * │──────────────────────────────────────────────────> Time
    * │     ^      ^          ^   ^^^  ^ ^ ^     ^^^ ^     Stake events
    *
    * @dev Reverts if:
    * - `_maxStakeLimit` == 0
    * - `_maxStakeLimit` >= 2^96
    * - `_maxStakeLimit` < `_stakeLimitIncreasePerBlock`
    * - `_maxStakeLimit` / `_stakeLimitIncreasePerBlock` >= 2^32 (only if `_stakeLimitIncreasePerBlock` != 0)
    *
    * Emits `StakingLimitSet` event
    *
    * @param _maxStakeLimit max stake limit value
    * @param _stakeLimitIncreasePerBlock stake limit increase per single block
    */
    function setStakingLimit(uint256 _maxStakeLimit, uint256 _stakeLimitIncreasePerBlock) external {
        _auth(STAKING_CONTROL_ROLE);

        STAKING_STATE_POSITION.setStorageStakeLimitStruct(
            STAKING_STATE_POSITION.getStorageStakeLimitStruct().setStakingLimit(
                _maxStakeLimit,
                _stakeLimitIncreasePerBlock
            )
        );

        emit StakingLimitSet(_maxStakeLimit, _stakeLimitIncreasePerBlock);
    }

    /**
    * @notice Removes the staking rate limit
    *
    * Emits `StakingLimitRemoved` event
    */
    function removeStakingLimit() external {
        _auth(STAKING_CONTROL_ROLE);

        STAKING_STATE_POSITION.setStorageStakeLimitStruct(
            STAKING_STATE_POSITION.getStorageStakeLimitStruct().removeStakingLimit()
        );

        emit StakingLimitRemoved();
    }

    /**
    * @notice Check staking state: whether it's paused or not
    */
    function isStakingPaused() external view returns (bool) {
        return STAKING_STATE_POSITION.getStorageStakeLimitStruct().isStakingPaused();
    }

    /**
    * @notice Returns how much Ether can be staked in the current block
    * @dev Special return values:
    * - 2^256 - 1 if staking is unlimited;
    * - 0 if staking is paused or if limit is exhausted.
    */
    function getCurrentStakeLimit() public view returns (uint256) {
        return _getCurrentStakeLimit(STAKING_STATE_POSITION.getStorageStakeLimitStruct());
    }

    /**
    * @notice Returns full info about current stake limit params and state
    * @dev Might be used for the advanced integration requests.
    * @return isStakingPaused staking pause state (equivalent to return of isStakingPaused())
    * @return isStakingLimitSet whether the stake limit is set
    * @return currentStakeLimit current stake limit (equivalent to return of getCurrentStakeLimit())
    * @return maxStakeLimit max stake limit
    * @return maxStakeLimitGrowthBlocks blocks needed to restore max stake limit from the fully exhausted state
    * @return prevStakeLimit previously reached stake limit
    * @return prevStakeBlockNumber previously seen block number
    */
    function getStakeLimitFullInfo() external view returns (
        bool isStakingPaused,
        bool isStakingLimitSet,
        uint256 currentStakeLimit,
        uint256 maxStakeLimit,
        uint256 maxStakeLimitGrowthBlocks,
        uint256 prevStakeLimit,
        uint256 prevStakeBlockNumber
    ) {
        StakeLimitState.Data memory stakeLimitData = STAKING_STATE_POSITION.getStorageStakeLimitStruct();

        isStakingPaused = stakeLimitData.isStakingPaused();
        isStakingLimitSet = stakeLimitData.isStakingLimitSet();

        currentStakeLimit = _getCurrentStakeLimit(stakeLimitData);

        maxStakeLimit = stakeLimitData.maxStakeLimit;
        maxStakeLimitGrowthBlocks = stakeLimitData.maxStakeLimitGrowthBlocks;
        prevStakeLimit = stakeLimitData.prevStakeLimit;
        prevStakeBlockNumber = stakeLimitData.prevStakeBlockNumber;
    }

    /**
    * @notice Send funds to the pool
    * @dev Users are able to submit their funds by transacting to the fallback function.
    * Unlike vanilla Eth2.0 Deposit contract, accepting only 32-Ether transactions, Lido
    * accepts payments of any size. Submitted Ethers are stored in Buffer until someone calls
    * depositBufferedEther() and pushes them to the ETH2 Deposit contract.
    */
    function() external payable {
        // protection against accidental submissions by calling non-existent function
        require(msg.data.length == 0, "NON_EMPTY_DATA");
        _submit(0);
    }

    /**
    * @notice Send funds to the pool with optional _referral parameter
    * @dev This function is alternative way to submit funds. Supports optional referral address.
    * @return Amount of StETH shares generated
    */
    function submit(address _referral) external payable returns (uint256) {
        return _submit(_referral);
    }

    /**
    * @notice A payable function for execution layer rewards. Can be called only by ExecutionLayerRewardsVault contract
    * @dev We need a dedicated function because funds received by the default payable function
    * are treated as a user deposit
    */
    function receiveELRewards() external payable {
        require(msg.sender == EL_REWARDS_VAULT_POSITION.getStorageAddress());

        TOTAL_EL_REWARDS_COLLECTED_POSITION.setStorageUint256(
            TOTAL_EL_REWARDS_COLLECTED_POSITION.getStorageUint256().add(msg.value));

        emit ELRewardsReceived(msg.value);
    }

    /**
    * @notice Deposits buffered ethers to the official DepositContract.
    * @dev This function is separated from submit() to reduce the cost of sending funds.
    */
    function depositBufferedEther() external {
        _auth(DEPOSIT_ROLE);

        return _depositBufferedEther(DEFAULT_MAX_DEPOSITS_PER_CALL);
    }

    /**
    * @notice Deposits buffered ethers to the official DepositContract, making no more than `_maxDeposits` deposit calls.
    * @dev This function is separated from submit() to reduce the cost of sending funds.
    */
    function depositBufferedEther(uint256 _maxDeposits) external {
        _auth(DEPOSIT_ROLE);

        return _depositBufferedEther(_maxDeposits);
    }

    function burnShares(address _account, uint256 _sharesAmount)
        external
        authP(BURN_ROLE, arr(_account, _sharesAmount))
        returns (uint256 newTotalShares)
    {
        return _burnShares(_account, _sharesAmount);
    }

    /**
    * @notice Stop pool routine operations
    */
    function stop() external {
        _auth(PAUSE_ROLE);

        _stop();
        _pauseStaking();
    }

    /**
    * @notice Resume pool routine operations
    * @dev Staking should be resumed manually after this call using the desired limits
    */
    function resume() external {
        _auth(RESUME_ROLE);

        _resume();
        _resumeStaking();
    }

    /**
    * @notice Set fee rate to `_feeBasisPoints` basis points.
    * The fees are accrued when:
    * - oracles report staking results (beacon chain balance increase)
    * - validators gain execution layer rewards (priority fees and MEV)
    * @param _feeBasisPoints Fee rate, in basis points
    */
    function setFee(uint16 _feeBasisPoints) external {
        _auth(MANAGE_FEE);

        _setBPValue(FEE_POSITION, _feeBasisPoints);
        emit FeeSet(_feeBasisPoints);
    }

    /**
    * @notice Set fee distribution
    * @param _treasuryFeeBasisPoints basis points go to the treasury,
    * @param _insuranceFeeBasisPoints basis points go to the insurance fund,
    * @param _operatorsFeeBasisPoints basis points go to node operators.
    * @dev The sum has to be 10 000.
    */
    function setFeeDistribution(
        uint16 _treasuryFeeBasisPoints,
        uint16 _insuranceFeeBasisPoints,
        uint16 _operatorsFeeBasisPoints
    )
        external
    {
        _auth(MANAGE_FEE);

        require(
            TOTAL_BASIS_POINTS == uint256(_treasuryFeeBasisPoints)
            .add(uint256(_insuranceFeeBasisPoints))
            .add(uint256(_operatorsFeeBasisPoints)),
            "FEES_DONT_ADD_UP"
        );

        _setBPValue(TREASURY_FEE_POSITION, _treasuryFeeBasisPoints);
        _setBPValue(INSURANCE_FEE_POSITION, _insuranceFeeBasisPoints);
        _setBPValue(NODE_OPERATORS_FEE_POSITION, _operatorsFeeBasisPoints);

        emit FeeDistributionSet(_treasuryFeeBasisPoints, _insuranceFeeBasisPoints, _operatorsFeeBasisPoints);
    }

    /**
    * @notice Set Lido protocol contracts (oracle, treasury, insurance fund).
    *
    * @dev Oracle contract specified here is allowed to make
    * periodical updates of beacon stats
    * by calling pushBeacon. Treasury contract specified here is used
    * to accumulate the protocol treasury fee. Insurance fund contract
    * specified here is used to accumulate the protocol insurance fee.
    *
    * @param _oracle oracle contract
    * @param _treasury treasury contract
    * @param _insuranceFund insurance fund contract
    */
    function setProtocolContracts(
        address _oracle,
        address _treasury,
        address _insuranceFund
    ) external {
        _auth(MANAGE_PROTOCOL_CONTRACTS_ROLE);

        _setProtocolContracts(_oracle, _treasury, _insuranceFund);
    }

    /**
    * @notice Set credentials to withdraw ETH on ETH 2.0 side after the phase 2 is launched to `_withdrawalCredentials`
    * @dev Note that setWithdrawalCredentials discards all unused signing keys as the signatures are invalidated.
    * @param _withdrawalCredentials withdrawal credentials field as defined in the Ethereum PoS consensus specs
    */
    function setWithdrawalCredentials(bytes32 _withdrawalCredentials) external {
        _auth(MANAGE_WITHDRAWAL_KEY);

        WITHDRAWAL_CREDENTIALS_POSITION.setStorageBytes32(_withdrawalCredentials);
        getOperators().trimUnusedKeys();

        emit WithdrawalCredentialsSet(_withdrawalCredentials);
    }

    /**
    * @dev Sets the address of LidoExecutionLayerRewardsVault contract
    * @param _executionLayerRewardsVault Execution layer rewards vault contract address
    */
    function setELRewardsVault(address _executionLayerRewardsVault) external {
        _auth(SET_EL_REWARDS_VAULT_ROLE);

        EL_REWARDS_VAULT_POSITION.setStorageAddress(_executionLayerRewardsVault);

        emit ELRewardsVaultSet(_executionLayerRewardsVault);
    }

    /**
    * @dev Sets limit on amount of ETH to withdraw from execution layer rewards vault per LidoOracle report
    * @param _limitPoints limit in basis points to amount of ETH to withdraw per LidoOracle report
    */
    function setELRewardsWithdrawalLimit(uint16 _limitPoints) external {
        _auth(SET_EL_REWARDS_WITHDRAWAL_LIMIT_ROLE);

        _setBPValue(EL_REWARDS_WITHDRAWAL_LIMIT_POSITION, _limitPoints);
        emit ELRewardsWithdrawalLimitSet(_limitPoints);
    }

    /**
    * @notice Updates beacon stats, collects rewards from LidoExecutionLayerRewardsVault and distributes all rewards if beacon balance increased
    * @dev periodically called by the Oracle contract
    * @param _beaconValidators number of Lido's keys in the beacon state
    * @param _beaconBalance summarized balance of Lido-controlled keys in wei
    */
    function handleOracleReport(uint256 _beaconValidators, uint256 _beaconBalance) external whenNotStopped {
        require(msg.sender == getOracle(), "APP_AUTH_FAILED");

        uint256 depositedValidators = DEPOSITED_VALIDATORS_POSITION.getStorageUint256();
        require(_beaconValidators <= depositedValidators, "REPORTED_MORE_DEPOSITED");

        uint256 beaconValidators = BEACON_VALIDATORS_POSITION.getStorageUint256();
        // Since the calculation of funds in the ingress queue is based on the number of validators
        // that are in a transient state (deposited but not seen on beacon yet), we can't decrease the previously
        // reported number (we'll be unable to figure out who is in the queue and count them).
        // See LIP-1 for details https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-1.md
        require(_beaconValidators >= beaconValidators, "REPORTED_LESS_VALIDATORS");
        uint256 appearedValidators = _beaconValidators.sub(beaconValidators);

        // RewardBase is the amount of money that is not included in the reward calculation
        // Just appeared validators * 32 added to the previously reported beacon balance
        uint256 rewardBase = (appearedValidators.mul(DEPOSIT_SIZE)).add(BEACON_BALANCE_POSITION.getStorageUint256());

        // Save the current beacon balance and validators to
        // calculate rewards on the next push
        BEACON_BALANCE_POSITION.setStorageUint256(_beaconBalance);
        BEACON_VALIDATORS_POSITION.setStorageUint256(_beaconValidators);

        // If LidoExecutionLayerRewardsVault address is not set just do as if there were no execution layer rewards at all
        // Otherwise withdraw all rewards and put them to the buffer
        // Thus, execution layer rewards are handled the same way as beacon rewards

        uint256 executionLayerRewards;
        address executionLayerRewardsVaultAddress = getELRewardsVault();

        if (executionLayerRewardsVaultAddress != address(0)) {
            executionLayerRewards = ILidoExecutionLayerRewardsVault(executionLayerRewardsVaultAddress).withdrawRewards(
                (_getTotalPooledEther() * EL_REWARDS_WITHDRAWAL_LIMIT_POSITION.getStorageUint256()) / TOTAL_BASIS_POINTS
            );

            if (executionLayerRewards != 0) {
                BUFFERED_ETHER_POSITION.setStorageUint256(_getBufferedEther().add(executionLayerRewards));
            }
        }

        // Don’t mint/distribute any protocol fee on the non-profitable Lido oracle report
        // (when beacon chain balance delta is zero or negative).
        // See ADR #3 for details: https://research.lido.fi/t/rewards-distribution-after-the-merge-architecture-decision-record/1535
        if (_beaconBalance > rewardBase) {
            uint256 rewards = _beaconBalance.sub(rewardBase);
            distributeFee(rewards.add(executionLayerRewards));
        }
    }

    /**
    * @notice Send funds to recovery Vault. Overrides default AragonApp behaviour
    * @param _token Token to be sent to recovery vault
    */
    function transferToVault(address _token) external {
        require(allowRecoverability(_token), "RECOVER_DISALLOWED");
        address vault = getRecoveryVault();
        require(vault != address(0), "RECOVER_VAULT_ZERO");

        uint256 balance;
        if (_token == ETH) {
            balance = _getUnaccountedEther();
            // Transfer replaced by call to prevent transfer gas amount issue
            require(vault.call.value(balance)(), "RECOVER_TRANSFER_FAILED");
        } else {
            ERC20 token = ERC20(_token);
            balance = token.staticBalanceOf(this);
            // safeTransfer comes from overridden default implementation
            require(token.safeTransfer(vault, balance), "RECOVER_TOKEN_TRANSFER_FAILED");
        }

        emit RecoverToVault(vault, _token, balance);
    }

    /**
    * @notice Returns staking rewards fee rate
    */
    function getFee() public view returns (uint16 feeBasisPoints) {
        return uint16(FEE_POSITION.getStorageUint256());
    }

    /**
    * @notice Returns fee distribution proportion
    */
    function getFeeDistribution()
        public
        view
        returns (
            uint16 treasuryFeeBasisPoints,
            uint16 insuranceFeeBasisPoints,
            uint16 operatorsFeeBasisPoints
        )
    {
        treasuryFeeBasisPoints = uint16(TREASURY_FEE_POSITION.getStorageUint256());
        insuranceFeeBasisPoints = uint16(INSURANCE_FEE_POSITION.getStorageUint256());
        operatorsFeeBasisPoints = uint16(NODE_OPERATORS_FEE_POSITION.getStorageUint256());
    }

    /**
    * @notice Returns current credentials to withdraw ETH on ETH 2.0 side after the phase 2 is launched
    */
    function getWithdrawalCredentials() public view returns (bytes32) {
        return WITHDRAWAL_CREDENTIALS_POSITION.getStorageBytes32();
    }

    /**
    * @notice Get the amount of Ether temporary buffered on this contract balance
    * @dev Buffered balance is kept on the contract from the moment the funds are received from user
    * until the moment they are actually sent to the official Deposit contract.
    * @return amount of buffered funds in wei
    */
    function getBufferedEther() external view returns (uint256) {
        return _getBufferedEther();
    }

    /**
    * @notice Get total amount of execution layer rewards collected to Lido contract
    * @dev Ether got through LidoExecutionLayerRewardsVault is kept on this contract's balance the same way
    * as other buffered Ether is kept (until it gets deposited)
    * @return amount of funds received as execution layer rewards (in wei)
    */
    function getTotalELRewardsCollected() external view returns (uint256) {
        return TOTAL_EL_REWARDS_COLLECTED_POSITION.getStorageUint256();
    }

    /**
    * @notice Get limit in basis points to amount of ETH to withdraw per LidoOracle report
    * @return limit in basis points to amount of ETH to withdraw per LidoOracle report
    */
    function getELRewardsWithdrawalLimit() external view returns (uint256) {
        return EL_REWARDS_WITHDRAWAL_LIMIT_POSITION.getStorageUint256();
    }

    /**
    * @notice Gets deposit contract handle
    */
    function getDepositContract() public view returns (IDepositContract) {
        return IDepositContract(DEPOSIT_CONTRACT_POSITION.getStorageAddress());
    }

    /**
    * @notice Gets authorized oracle address
    * @return address of oracle contract
    */
    function getOracle() public view returns (address) {
        return ORACLE_POSITION.getStorageAddress();
    }

    /**
    * @notice Gets node operators registry interface handle
    */
    function getOperators() public view returns (INodeOperatorsRegistry) {
        return INodeOperatorsRegistry(NODE_OPERATORS_REGISTRY_POSITION.getStorageAddress());
    }

    /**
    * @notice Returns the treasury address
    */
    function getTreasury() public view returns (address) {
        return TREASURY_POSITION.getStorageAddress();
    }

    /**
    * @notice Returns the insurance fund address
    */
    function getInsuranceFund() public view returns (address) {
        return INSURANCE_FUND_POSITION.getStorageAddress();
    }

    /**
    * @notice Returns the key values related to Beacon-side
    * @return depositedValidators - number of deposited validators
    * @return beaconValidators - number of Lido's validators visible in the Beacon state, reported by oracles
    * @return beaconBalance - total amount of Beacon-side Ether (sum of all the balances of Lido validators)
    */
    function getBeaconStat() public view returns (uint256 depositedValidators, uint256 beaconValidators, uint256 beaconBalance) {
        depositedValidators = DEPOSITED_VALIDATORS_POSITION.getStorageUint256();
        beaconValidators = BEACON_VALIDATORS_POSITION.getStorageUint256();
        beaconBalance = BEACON_BALANCE_POSITION.getStorageUint256();
    }

    /**
    * @notice Returns address of the contract set as LidoExecutionLayerRewardsVault
    */
    function getELRewardsVault() public view returns (address) {
        return EL_REWARDS_VAULT_POSITION.getStorageAddress();
    }

    /**
    * @dev Internal function to set authorized oracle address
    * @param _oracle oracle contract
    */
    function _setProtocolContracts(address _oracle, address _treasury, address _insuranceFund) internal {
        require(_oracle != address(0), "ORACLE_ZERO_ADDRESS");
        require(_treasury != address(0), "TREASURY_ZERO_ADDRESS");
        require(_insuranceFund != address(0), "INSURANCE_FUND_ZERO_ADDRESS");

        ORACLE_POSITION.setStorageAddress(_oracle);
        TREASURY_POSITION.setStorageAddress(_treasury);
        INSURANCE_FUND_POSITION.setStorageAddress(_insuranceFund);

        emit ProtocolContactsSet(_oracle, _treasury, _insuranceFund);
    }

    /**
    * @dev Process user deposit, mints liquid tokens and increase the pool buffer
    * @param _referral address of referral.
    * @return amount of StETH shares generated
    */
    function _submit(address _referral) internal returns (uint256) {
        require(msg.value != 0, "ZERO_DEPOSIT");

        StakeLimitState.Data memory stakeLimitData = STAKING_STATE_POSITION.getStorageStakeLimitStruct();
        require(!stakeLimitData.isStakingPaused(), "STAKING_PAUSED");

        if (stakeLimitData.isStakingLimitSet()) {
            uint256 currentStakeLimit = stakeLimitData.calculateCurrentStakeLimit();

            require(msg.value <= currentStakeLimit, "STAKE_LIMIT");

            STAKING_STATE_POSITION.setStorageStakeLimitStruct(
                stakeLimitData.updatePrevStakeLimit(currentStakeLimit - msg.value)
            );
        }

        uint256 sharesAmount = getSharesByPooledEth(msg.value);
        if (sharesAmount == 0) {
            // totalControlledEther is 0: either the first-ever deposit or complete slashing
            // assume that shares correspond to Ether 1-to-1
            sharesAmount = msg.value;
        }

        _mintShares(msg.sender, sharesAmount);

        BUFFERED_ETHER_POSITION.setStorageUint256(_getBufferedEther().add(msg.value));
        emit Submitted(msg.sender, msg.value, _referral);

        _emitTransferAfterMintingShares(msg.sender, sharesAmount);
        return sharesAmount;
    }

    /**
    * @dev Emits {Transfer} and {TransferShares} events where `from` is 0 address. Indicates mint events.
    */
    function _emitTransferAfterMintingShares(address _to, uint256 _sharesAmount) internal {
        emit Transfer(address(0), _to, getPooledEthByShares(_sharesAmount));
        emit TransferShares(address(0), _to, _sharesAmount);
    }

    /**
    * @dev Deposits buffered eth to the DepositContract and assigns chunked deposits to node operators
    */
    function _depositBufferedEther(uint256 _maxDeposits) internal whenNotStopped {
        uint256 buffered = _getBufferedEther();
        if (buffered >= DEPOSIT_SIZE) {
            uint256 unaccounted = _getUnaccountedEther();
            uint256 numDeposits = buffered.div(DEPOSIT_SIZE);
            _markAsUnbuffered(_ETH2Deposit(numDeposits < _maxDeposits ? numDeposits : _maxDeposits));
            assert(_getUnaccountedEther() == unaccounted);
        }
    }

    /**
    * @dev Performs deposits to the ETH 2.0 side
    * @param _numDeposits Number of deposits to perform
    * @return actually deposited Ether amount
    */
    function _ETH2Deposit(uint256 _numDeposits) internal returns (uint256) {
        (bytes memory pubkeys, bytes memory signatures) = getOperators().assignNextSigningKeys(_numDeposits);

        if (pubkeys.length == 0) {
            return 0;
        }

        require(pubkeys.length.mod(PUBKEY_LENGTH) == 0, "REGISTRY_INCONSISTENT_PUBKEYS_LEN");
        require(signatures.length.mod(SIGNATURE_LENGTH) == 0, "REGISTRY_INCONSISTENT_SIG_LEN");

        uint256 numKeys = pubkeys.length.div(PUBKEY_LENGTH);
        require(numKeys == signatures.length.div(SIGNATURE_LENGTH), "REGISTRY_INCONSISTENT_SIG_COUNT");

        for (uint256 i = 0; i < numKeys; ++i) {
            bytes memory pubkey = BytesLib.slice(pubkeys, i * PUBKEY_LENGTH, PUBKEY_LENGTH);
            bytes memory signature = BytesLib.slice(signatures, i * SIGNATURE_LENGTH, SIGNATURE_LENGTH);
            _stake(pubkey, signature);
        }

        DEPOSITED_VALIDATORS_POSITION.setStorageUint256(
            DEPOSITED_VALIDATORS_POSITION.getStorageUint256().add(numKeys)
        );

        return numKeys.mul(DEPOSIT_SIZE);
    }

    /**
    * @dev Invokes a deposit call to the official Deposit contract
    * @param _pubkey Validator to stake for
    * @param _signature Signature of the deposit call
    */
    function _stake(bytes memory _pubkey, bytes memory _signature) internal {
        bytes32 withdrawalCredentials = getWithdrawalCredentials();
        require(withdrawalCredentials != 0, "EMPTY_WITHDRAWAL_CREDENTIALS");

        uint256 value = DEPOSIT_SIZE;

        // The following computations and Merkle tree-ization will make official Deposit contract happy
        uint256 depositAmount = value.div(DEPOSIT_AMOUNT_UNIT);
        assert(depositAmount.mul(DEPOSIT_AMOUNT_UNIT) == value);    // properly rounded

        // Compute deposit data root (`DepositData` hash tree root) according to deposit_contract.sol
        bytes32 pubkeyRoot = sha256(_pad64(_pubkey));
        bytes32 signatureRoot = sha256(
            abi.encodePacked(
                sha256(BytesLib.slice(_signature, 0, 64)),
                sha256(_pad64(BytesLib.slice(_signature, 64, SIGNATURE_LENGTH.sub(64))))
            )
        );

        bytes32 depositDataRoot = sha256(
            abi.encodePacked(
                sha256(abi.encodePacked(pubkeyRoot, withdrawalCredentials)),
                sha256(abi.encodePacked(_toLittleEndian64(depositAmount), signatureRoot))
            )
        );

        uint256 targetBalance = address(this).balance.sub(value);

        getDepositContract().deposit.value(value)(
            _pubkey, abi.encodePacked(withdrawalCredentials), _signature, depositDataRoot);
        require(address(this).balance == targetBalance, "EXPECTING_DEPOSIT_TO_HAPPEN");
    }

    /**
    * @dev Distributes fee portion of the rewards by minting and distributing corresponding amount of liquid tokens.
    * @param _totalRewards Total rewards accrued on the Ethereum 2.0 side in wei
    */
    function distributeFee(uint256 _totalRewards) internal {
        // We need to take a defined percentage of the reported reward as a fee, and we do
        // this by minting new token shares and assigning them to the fee recipients (see
        // StETH docs for the explanation of the shares mechanics). The staking rewards fee
        // is defined in basis points (1 basis point is equal to 0.01%, 10000 (TOTAL_BASIS_POINTS) is 100%).
        //
        // Since we've increased totalPooledEther by _totalRewards (which is already
        // performed by the time this function is called), the combined cost of all holders'
        // shares has became _totalRewards StETH tokens more, effectively splitting the reward
        // between each token holder proportionally to their token share.
        //
        // Now we want to mint new shares to the fee recipient, so that the total cost of the
        // newly-minted shares exactly corresponds to the fee taken:
        //
        // shares2mint * newShareCost = (_totalRewards * feeBasis) / TOTAL_BASIS_POINTS
        // newShareCost = newTotalPooledEther / (prevTotalShares + shares2mint)
        //
        // which follows to:
        //
        //                        _totalRewards * feeBasis * prevTotalShares
        // shares2mint = --------------------------------------------------------------
        //                 (newTotalPooledEther * TOTAL_BASIS_POINTS) - (feeBasis * _totalRewards)
        //
        // The effect is that the given percentage of the reward goes to the fee recipient, and
        // the rest of the reward is distributed between token holders proportionally to their
        // token shares.
        uint256 feeBasis = getFee();
        uint256 shares2mint = (
            _totalRewards.mul(feeBasis).mul(_getTotalShares())
            .div(
                _getTotalPooledEther().mul(TOTAL_BASIS_POINTS)
                .sub(feeBasis.mul(_totalRewards))
            )
        );

        // Mint the calculated amount of shares to this contract address. This will reduce the
        // balances of the holders, as if the fee was taken in parts from each of them.
        _mintShares(address(this), shares2mint);

        (,uint16 insuranceFeeBasisPoints, uint16 operatorsFeeBasisPoints) = getFeeDistribution();

        uint256 toInsuranceFund = shares2mint.mul(insuranceFeeBasisPoints).div(TOTAL_BASIS_POINTS);
        address insuranceFund = getInsuranceFund();
        _transferShares(address(this), insuranceFund, toInsuranceFund);
        _emitTransferAfterMintingShares(insuranceFund, toInsuranceFund);

        uint256 distributedToOperatorsShares = _distributeNodeOperatorsReward(
            shares2mint.mul(operatorsFeeBasisPoints).div(TOTAL_BASIS_POINTS)
        );

        // Transfer the rest of the fee to treasury
        uint256 toTreasury = shares2mint.sub(toInsuranceFund).sub(distributedToOperatorsShares);

        address treasury = getTreasury();
        _transferShares(address(this), treasury, toTreasury);
        _emitTransferAfterMintingShares(treasury, toTreasury);
    }

    /**
    *  @dev Internal function to distribute reward to node operators
    *  @param _sharesToDistribute amount of shares to distribute
    *  @return actual amount of shares that was transferred to node operators as a reward
    */
    function _distributeNodeOperatorsReward(uint256 _sharesToDistribute) internal returns (uint256 distributed) {
        (address[] memory recipients, uint256[] memory shares) = getOperators().getRewardsDistribution(_sharesToDistribute);

        assert(recipients.length == shares.length);

        distributed = 0;
        for (uint256 idx = 0; idx < recipients.length; ++idx) {
            _transferShares(
                address(this),
                recipients[idx],
                shares[idx]
            );
            _emitTransferAfterMintingShares(recipients[idx], shares[idx]);
            distributed = distributed.add(shares[idx]);
        }
    }

    /**
    * @dev Records a deposit to the deposit_contract.deposit function
    * @param _amount Total amount deposited to the ETH 2.0 side
    */
    function _markAsUnbuffered(uint256 _amount) internal {
        BUFFERED_ETHER_POSITION.setStorageUint256(
            BUFFERED_ETHER_POSITION.getStorageUint256().sub(_amount));

        emit Unbuffered(_amount);
    }

    /**
    * @dev Write a value nominated in basis points
    */
    function _setBPValue(bytes32 _slot, uint16 _value) internal {
        require(_value <= TOTAL_BASIS_POINTS, "VALUE_OVER_100_PERCENT");
        _slot.setStorageUint256(uint256(_value));
    }

    /**
    * @dev Gets the amount of Ether temporary buffered on this contract balance
    */
    function _getBufferedEther() internal view returns (uint256) {
        uint256 buffered = BUFFERED_ETHER_POSITION.getStorageUint256();
        assert(address(this).balance >= buffered);

        return buffered;
    }

    /**
    * @dev Gets unaccounted (excess) Ether on this contract balance
    */
    function _getUnaccountedEther() internal view returns (uint256) {
        return address(this).balance.sub(_getBufferedEther());
    }

    /**
    * @dev Calculates and returns the total base balance (multiple of 32) of validators in transient state,
    *      i.e. submitted to the official Deposit contract but not yet visible in the beacon state.
    * @return transient balance in wei (1e-18 Ether)
    */
    function _getTransientBalance() internal view returns (uint256) {
        uint256 depositedValidators = DEPOSITED_VALIDATORS_POSITION.getStorageUint256();
        uint256 beaconValidators = BEACON_VALIDATORS_POSITION.getStorageUint256();
        // beaconValidators can never be less than deposited ones.
        assert(depositedValidators >= beaconValidators);
        return depositedValidators.sub(beaconValidators).mul(DEPOSIT_SIZE);
    }

    /**
    * @dev Gets the total amount of Ether controlled by the system
    * @return total balance in wei
    */
    function _getTotalPooledEther() internal view returns (uint256) {
        return _getBufferedEther().add(
            BEACON_BALANCE_POSITION.getStorageUint256()
        ).add(_getTransientBalance());
    }

    /**
    * @dev Padding memory array with zeroes up to 64 bytes on the right
    * @param _b Memory array of size 32 .. 64
    */
    function _pad64(bytes memory _b) internal pure returns (bytes memory) {
        assert(_b.length >= 32 && _b.length <= 64);
        if (64 == _b.length)
            return _b;

        bytes memory zero32 = new bytes(32);
        assembly { mstore(add(zero32, 0x20), 0) }

        if (32 == _b.length)
            return BytesLib.concat(_b, zero32);
        else
            return BytesLib.concat(_b, BytesLib.slice(zero32, 0, uint256(64).sub(_b.length)));
    }

    /**
    * @dev Converting value to little endian bytes and padding up to 32 bytes on the right
    * @param _value Number less than `2**64` for compatibility reasons
    */
    function _toLittleEndian64(uint256 _value) internal pure returns (uint256 result) {
        result = 0;
        uint256 temp_value = _value;
        for (uint256 i = 0; i < 8; ++i) {
            result = (result << 8) | (temp_value & 0xFF);
            temp_value >>= 8;
        }

        assert(0 == temp_value);    // fully converted
        result <<= (24 * 8);
    }

    function _pauseStaking() internal {
        STAKING_STATE_POSITION.setStorageStakeLimitStruct(
            STAKING_STATE_POSITION.getStorageStakeLimitStruct().setStakeLimitPauseState(true)
        );

        emit StakingPaused();
    }

    function _resumeStaking() internal {
        STAKING_STATE_POSITION.setStorageStakeLimitStruct(
            STAKING_STATE_POSITION.getStorageStakeLimitStruct().setStakeLimitPauseState(false)
        );

        emit StakingResumed();
    }

    function _getCurrentStakeLimit(StakeLimitState.Data memory _stakeLimitData) internal view returns(uint256) {
        if (_stakeLimitData.isStakingPaused()) {
            return 0;
        }
        if (!_stakeLimitData.isStakingLimitSet()) {
            return uint256(-1);
        }

        return _stakeLimitData.calculateCurrentStakeLimit();
    }

    /**
    * @dev Size-efficient analog of the `auth(_role)` modifier
    * @param _role Permission name
    */
    function _auth(bytes32 _role) internal view auth(_role) {
        // no-op
    }
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;

import "./AppStorage.sol";
import "../acl/ACLSyntaxSugar.sol";
import "../common/Autopetrified.sol";
import "../common/ConversionHelpers.sol";
import "../common/ReentrancyGuard.sol";
import "../common/VaultRecoverable.sol";
import "../evmscript/EVMScriptRunner.sol";


// Contracts inheriting from AragonApp are, by default, immediately petrified upon deployment so
// that they can never be initialized.
// Unless overriden, this behaviour enforces those contracts to be usable only behind an AppProxy.
// ReentrancyGuard, EVMScriptRunner, and ACLSyntaxSugar are not directly used by this contract, but
// are included so that they are automatically usable by subclassing contracts
contract AragonApp is AppStorage, Autopetrified, VaultRecoverable, ReentrancyGuard, EVMScriptRunner, ACLSyntaxSugar {
    string private constant ERROR_AUTH_FAILED = "APP_AUTH_FAILED";

    modifier auth(bytes32 _role) {
        require(canPerform(msg.sender, _role, new uint256[](0)), ERROR_AUTH_FAILED);
        _;
    }

    modifier authP(bytes32 _role, uint256[] _params) {
        require(canPerform(msg.sender, _role, _params), ERROR_AUTH_FAILED);
        _;
    }

    /**
    * @dev Check whether an action can be performed by a sender for a particular role on this app
    * @param _sender Sender of the call
    * @param _role Role on this app
    * @param _params Permission params for the role
    * @return Boolean indicating whether the sender has the permissions to perform the action.
    *         Always returns false if the app hasn't been initialized yet.
    */
    function canPerform(address _sender, bytes32 _role, uint256[] _params) public view returns (bool) {
        if (!hasInitialized()) {
            return false;
        }

        IKernel linkedKernel = kernel();
        if (address(linkedKernel) == address(0)) {
            return false;
        }

        return linkedKernel.hasPermission(
            _sender,
            address(this),
            _role,
            ConversionHelpers.dangerouslyCastUintArrayToBytes(_params)
        );
    }

    /**
    * @dev Get the recovery vault for the app
    * @return Recovery vault address for the app
    */
    function getRecoveryVault() public view returns (address) {
        // Funds recovery via a vault is only available when used with a kernel
        return kernel().getRecoveryVault(); // if kernel is not set, it will revert
    }
}

// See https://github.com/OpenZeppelin/openzeppelin-solidity/blob/d51e38758e1d985661534534d5c61e27bece5042/contracts/math/SafeMath.sol
// Adapted to use pragma ^0.4.24 and satisfy our linter rules

pragma solidity ^0.4.24;


/**
 * @title SafeMath
 * @dev Math operations with safety checks that revert on error
 */
library SafeMath {
    string private constant ERROR_ADD_OVERFLOW = "MATH_ADD_OVERFLOW";
    string private constant ERROR_SUB_UNDERFLOW = "MATH_SUB_UNDERFLOW";
    string private constant ERROR_MUL_OVERFLOW = "MATH_MUL_OVERFLOW";
    string private constant ERROR_DIV_ZERO = "MATH_DIV_ZERO";

    /**
    * @dev Multiplies two numbers, reverts on 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-solidity/pull/522
        if (_a == 0) {
            return 0;
        }

        uint256 c = _a * _b;
        require(c / _a == _b, ERROR_MUL_OVERFLOW);

        return c;
    }

    /**
    * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
    */
    function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
        require(_b > 0, ERROR_DIV_ZERO); // Solidity only automatically asserts when dividing by 0
        uint256 c = _a / _b;
        // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold

        return c;
    }

    /**
    * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
    */
    function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
        require(_b <= _a, ERROR_SUB_UNDERFLOW);
        uint256 c = _a - _b;

        return c;
    }

    /**
    * @dev Adds two numbers, reverts on overflow.
    */
    function add(uint256 _a, uint256 _b) internal pure returns (uint256) {
        uint256 c = _a + _b;
        require(c >= _a, ERROR_ADD_OVERFLOW);

        return c;
    }

    /**
    * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
    * reverts when dividing by zero.
    */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, ERROR_DIV_ZERO);
        return a % b;
    }
}

// See https://github.com/OpenZeppelin/openzeppelin-solidity/blob/d51e38758e1d985661534534d5c61e27bece5042/contracts/math/SafeMath.sol
// Adapted for uint64, pragma ^0.4.24, and satisfying our linter rules
// Also optimized the mul() implementation, see https://github.com/aragon/aragonOS/pull/417

pragma solidity ^0.4.24;


/**
 * @title SafeMath64
 * @dev Math operations for uint64 with safety checks that revert on error
 */
library SafeMath64 {
    string private constant ERROR_ADD_OVERFLOW = "MATH64_ADD_OVERFLOW";
    string private constant ERROR_SUB_UNDERFLOW = "MATH64_SUB_UNDERFLOW";
    string private constant ERROR_MUL_OVERFLOW = "MATH64_MUL_OVERFLOW";
    string private constant ERROR_DIV_ZERO = "MATH64_DIV_ZERO";

    /**
    * @dev Multiplies two numbers, reverts on overflow.
    */
    function mul(uint64 _a, uint64 _b) internal pure returns (uint64) {
        uint256 c = uint256(_a) * uint256(_b);
        require(c < 0x010000000000000000, ERROR_MUL_OVERFLOW); // 2**64 (less gas this way)

        return uint64(c);
    }

    /**
    * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
    */
    function div(uint64 _a, uint64 _b) internal pure returns (uint64) {
        require(_b > 0, ERROR_DIV_ZERO); // Solidity only automatically asserts when dividing by 0
        uint64 c = _a / _b;
        // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold

        return c;
    }

    /**
    * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
    */
    function sub(uint64 _a, uint64 _b) internal pure returns (uint64) {
        require(_b <= _a, ERROR_SUB_UNDERFLOW);
        uint64 c = _a - _b;

        return c;
    }

    /**
    * @dev Adds two numbers, reverts on overflow.
    */
    function add(uint64 _a, uint64 _b) internal pure returns (uint64) {
        uint64 c = _a + _b;
        require(c >= _a, ERROR_ADD_OVERFLOW);

        return c;
    }

    /**
    * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
    * reverts when dividing by zero.
    */
    function mod(uint64 a, uint64 b) internal pure returns (uint64) {
        require(b != 0, ERROR_DIV_ZERO);
        return a % b;
    }
}

/*
 * @title Solidity Bytes Arrays Utils
 * @author Gonçalo Sá <[email protected]>
 *
 * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
 *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
 */

pragma solidity ^0.4.19;


library BytesLib {
    function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes) {
        bytes memory tempBytes;

        assembly {
            // Get a location of some free memory and store it in tempBytes as
            // Solidity does for memory variables.
            tempBytes := mload(0x40)

            // Store the length of the first bytes array at the beginning of
            // the memory for tempBytes.
            let length := mload(_preBytes)
            mstore(tempBytes, length)

            // Maintain a memory counter for the current write location in the
            // temp bytes array by adding the 32 bytes for the array length to
            // the starting location.
            let mc := add(tempBytes, 0x20)
            // Stop copying when the memory counter reaches the length of the
            // first bytes array.
            let end := add(mc, length)

            for {
                // Initialize a copy counter to the start of the _preBytes data,
                // 32 bytes into its memory.
                let cc := add(_preBytes, 0x20)
            } lt(mc, end) {
                // Increase both counters by 32 bytes each iteration.
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                // Write the _preBytes data into the tempBytes memory 32 bytes
                // at a time.
                mstore(mc, mload(cc))
            }

            // Add the length of _postBytes to the current length of tempBytes
            // and store it as the new length in the first 32 bytes of the
            // tempBytes memory.
            length := mload(_postBytes)
            mstore(tempBytes, add(length, mload(tempBytes)))

            // Move the memory counter back from a multiple of 0x20 to the
            // actual end of the _preBytes data.
            mc := end
            // Stop copying when the memory counter reaches the new combined
            // length of the arrays.
            end := add(mc, length)

            for {
                let cc := add(_postBytes, 0x20)
            } lt(mc, end) {
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                mstore(mc, mload(cc))
            }

            // Update the free-memory pointer by padding our last write location
            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
            // next 32 byte block, then round down to the nearest multiple of
            // 32. If the sum of the length of the two arrays is zero then add 
            // one before rounding down to leave a blank 32 bytes (the length block with 0).
            mstore(0x40, and(
              add(add(end, iszero(add(length, mload(_preBytes)))), 31),
              not(31) // Round down to the nearest 32 bytes.
            ))
        }

        return tempBytes;
    }

    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
        assembly {
            // Read the first 32 bytes of _preBytes storage, which is the length
            // of the array. (We don't need to use the offset into the slot
            // because arrays use the entire slot.)
            let fslot := sload(_preBytes_slot)
            // Arrays of 31 bytes or less have an even value in their slot,
            // while longer arrays have an odd value. The actual length is
            // the slot divided by two for odd values, and the lowest order
            // byte divided by two for even values.
            // If the slot is even, bitwise and the slot with 255 and divide by
            // two to get the length. If the slot is odd, bitwise and the slot
            // with -1 and divide by two.
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)
            let newlength := add(slength, mlength)
            // slength can contain both the length and contents of the array
            // if length < 32 bytes so let's prepare for that
            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
            switch add(lt(slength, 32), lt(newlength, 32))
            case 2 {
                // Since the new array still fits in the slot, we just need to
                // update the contents of the slot.
                // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
                sstore(
                    _preBytes_slot,
                    // all the modifications to the slot are inside this
                    // next block
                    add(
                        // we can just add to the slot contents because the
                        // bytes we want to change are the LSBs
                        fslot,
                        add(
                            mul(
                                div(
                                    // load the bytes from memory
                                    mload(add(_postBytes, 0x20)),
                                    // zero all bytes to the right
                                    exp(0x100, sub(32, mlength))
                                ),
                                // and now shift left the number of bytes to
                                // leave space for the length in the slot
                                exp(0x100, sub(32, newlength))
                            ),
                            // increase length by the double of the memory
                            // bytes length
                            mul(mlength, 2)
                        )
                    )
                )
            }
            case 1 {
                // The stored value fits in the slot, but the combined value
                // will exceed it.
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes_slot)
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes_slot, add(mul(newlength, 2), 1))

                // The contents of the _postBytes array start 32 bytes into
                // the structure. Our first read should obtain the `submod`
                // bytes that can fit into the unused space in the last word
                // of the stored array. To get this, we read 32 bytes starting
                // from `submod`, so the data we read overlaps with the array
                // contents by `submod` bytes. Masking the lowest-order
                // `submod` bytes allows us to add that value directly to the
                // stored value.

                let submod := sub(32, slength)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(
                    sc,
                    add(
                        and(
                            fslot,
                            0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
                        ),
                        and(mload(mc), mask)
                    )
                )

                for {
                    mc := add(mc, 0x20)
                    sc := add(sc, 1)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
            default {
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes_slot)
                // Start copying to the last used word of the stored array.
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes_slot, add(mul(newlength, 2), 1))

                // Copy over the first `submod` bytes of the new data as in
                // case 1 above.
                let slengthmod := mod(slength, 32)
                let mlengthmod := mod(mlength, 32)
                let submod := sub(32, slengthmod)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(sc, add(sload(sc), and(mload(mc), mask)))
                
                for { 
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
        }
    }

    function slice(bytes _bytes, uint _start, uint _length) internal  pure returns (bytes) {
        require(_bytes.length >= (_start + _length));

        bytes memory tempBytes;

        assembly {
            switch iszero(_length)
            case 0 {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)

                // The first word of the slice result is potentially a partial
                // word read from the original array. To read it, we calculate
                // the length of that partial word and start copying that many
                // bytes into the array. The first word we copy will start with
                // data we don't care about, but the last `lengthmod` bytes will
                // land at the beginning of the contents of the new array. When
                // we're done copying, we overwrite the full first word with
                // the actual length of the slice.
                let lengthmod := and(_length, 31)

                // The multiplication in the next line is necessary
                // because when slicing multiples of 32 bytes (lengthmod == 0)
                // the following copy loop was copying the origin's length
                // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // The multiplication in the next line has the same exact purpose
                    // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    mstore(mc, mload(cc))
                }

                mstore(tempBytes, _length)

                //update free-memory pointer
                //allocating the array padded to 32 bytes like the compiler does now
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            //if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    function toAddress(bytes _bytes, uint _start) internal  pure returns (address) {
        require(_bytes.length >= (_start + 20));
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint8(bytes _bytes, uint _start) internal  pure returns (uint8) {
        require(_bytes.length >= (_start + 1));
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }

    function toUint16(bytes _bytes, uint _start) internal  pure returns (uint16) {
        require(_bytes.length >= (_start + 2));
        uint16 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x2), _start))
        }

        return tempUint;
    }

    function toUint32(bytes _bytes, uint _start) internal  pure returns (uint32) {
        require(_bytes.length >= (_start + 4));
        uint32 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x4), _start))
        }

        return tempUint;
    }

    function toUint(bytes _bytes, uint _start) internal  pure returns (uint256) {
        require(_bytes.length >= (_start + 32));
        uint256 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x20), _start))
        }

        return tempUint;
    }

    function toBytes32(bytes _bytes, uint _start) internal  pure returns (bytes32) {
        require(_bytes.length >= (_start + 32));
        bytes32 tempBytes32;

        assembly {
            tempBytes32 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes32;
    }

    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
        bool success = true;

        assembly {
            let length := mload(_preBytes)

            // if lengths don't match the arrays are not equal
            switch eq(length, mload(_postBytes))
            case 1 {
                // cb is a circuit breaker in the for loop since there's
                //  no said feature for inline assembly loops
                // cb = 1 - don't breaker
                // cb = 0 - break
                let cb := 1

                let mc := add(_preBytes, 0x20)
                let end := add(mc, length)

                for {
                    let cc := add(_postBytes, 0x20)
                // the next line is the loop condition:
                // while(uint(mc < end) + cb == 2)
                } eq(add(lt(mc, end), cb), 2) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    // if any of these checks fails then arrays are not equal
                    if iszero(eq(mload(mc), mload(cc))) {
                        // unsuccess:
                        success := 0
                        cb := 0
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }

    function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) {
        bool success = true;

        assembly {
            // we know _preBytes_offset is 0
            let fslot := sload(_preBytes_slot)
            // Decode the length of the stored array like in concatStorage().
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)

            // if lengths don't match the arrays are not equal
            switch eq(slength, mlength)
            case 1 {
                // slength can contain both the length and contents of the array
                // if length < 32 bytes so let's prepare for that
                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                if iszero(iszero(slength)) {
                    switch lt(slength, 32)
                    case 1 {
                        // blank the last byte which is the length
                        fslot := mul(div(fslot, 0x100), 0x100)

                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                            // unsuccess:
                            success := 0
                        }
                    }
                    default {
                        // cb is a circuit breaker in the for loop since there's
                        //  no said feature for inline assembly loops
                        // cb = 1 - don't breaker
                        // cb = 0 - break
                        let cb := 1

                        // get the keccak hash to get the contents of the array
                        mstore(0x0, _preBytes_slot)
                        let sc := keccak256(0x0, 0x20)

                        let mc := add(_postBytes, 0x20)
                        let end := add(mc, mlength)

                        // the next line is the loop condition:
                        // while(uint(mc < end) + cb == 2)
                        for {} eq(add(lt(mc, end), cb), 2) {
                            sc := add(sc, 1)
                            mc := add(mc, 0x20)
                        } {
                            if iszero(eq(sload(sc), mload(mc))) {
                                // unsuccess:
                                success := 0
                                cb := 0
                            }
                        }
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }
}

// SPDX-FileCopyrightText: 2020 Lido <[email protected]>

// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.4.24;


/**
  * @title Liquid staking pool
  *
  * For the high-level description of the pool operation please refer to the paper.
  * Pool manages withdrawal keys and fees. It receives ether submitted by users on the ETH 1 side
  * and stakes it via the deposit_contract.sol contract. It doesn't hold ether on it's balance,
  * only a small portion (buffer) of it.
  * It also mints new tokens for rewards generated at the ETH 2.0 side.
  *
  * At the moment withdrawals are not possible in the beacon chain and there's no workaround.
  * Pool will be upgraded to an actual implementation when withdrawals are enabled
  * (Phase 1.5 or 2 of Eth2 launch, likely late 2022 or 2023).
  */
interface ILido {
    function totalSupply() external view returns (uint256);
    function getTotalShares() external view returns (uint256);

    /**
      * @notice Stop pool routine operations
      */
    function stop() external;

    /**
      * @notice Resume pool routine operations
      */
    function resume() external;

    /**
      * @notice Stops accepting new Ether to the protocol
      *
      * @dev While accepting new Ether is stopped, calls to the `submit` function,
      * as well as to the default payable function, will revert.
      *
      * Emits `StakingPaused` event.
      */
    function pauseStaking() external;

    /**
      * @notice Resumes accepting new Ether to the protocol (if `pauseStaking` was called previously)
      * NB: Staking could be rate-limited by imposing a limit on the stake amount
      * at each moment in time, see `setStakingLimit()` and `removeStakingLimit()`
      *
      * @dev Preserves staking limit if it was set previously
      *
      * Emits `StakingResumed` event
      */
    function resumeStaking() external;

    /**
      * @notice Sets the staking rate limit
      *
      * @dev Reverts if:
      * - `_maxStakeLimit` == 0
      * - `_maxStakeLimit` >= 2^96
      * - `_maxStakeLimit` < `_stakeLimitIncreasePerBlock`
      * - `_maxStakeLimit` / `_stakeLimitIncreasePerBlock` >= 2^32 (only if `_stakeLimitIncreasePerBlock` != 0)
      *
      * Emits `StakingLimitSet` event
      *
      * @param _maxStakeLimit max stake limit value
      * @param _stakeLimitIncreasePerBlock stake limit increase per single block
      */
    function setStakingLimit(uint256 _maxStakeLimit, uint256 _stakeLimitIncreasePerBlock) external;

    /**
      * @notice Removes the staking rate limit
      *
      * Emits `StakingLimitRemoved` event
      */
    function removeStakingLimit() external;

    /**
      * @notice Check staking state: whether it's paused or not
      */
    function isStakingPaused() external view returns (bool);

    /**
      * @notice Returns how much Ether can be staked in the current block
      * @dev Special return values:
      * - 2^256 - 1 if staking is unlimited;
      * - 0 if staking is paused or if limit is exhausted.
      */
    function getCurrentStakeLimit() external view returns (uint256);

    /**
      * @notice Returns full info about current stake limit params and state
      * @dev Might be used for the advanced integration requests.
      * @return isStakingPaused staking pause state (equivalent to return of isStakingPaused())
      * @return isStakingLimitSet whether the stake limit is set
      * @return currentStakeLimit current stake limit (equivalent to return of getCurrentStakeLimit())
      * @return maxStakeLimit max stake limit
      * @return maxStakeLimitGrowthBlocks blocks needed to restore max stake limit from the fully exhausted state
      * @return prevStakeLimit previously reached stake limit
      * @return prevStakeBlockNumber previously seen block number
      */
    function getStakeLimitFullInfo() external view returns (
        bool isStakingPaused,
        bool isStakingLimitSet,
        uint256 currentStakeLimit,
        uint256 maxStakeLimit,
        uint256 maxStakeLimitGrowthBlocks,
        uint256 prevStakeLimit,
        uint256 prevStakeBlockNumber
    );

    event Stopped();
    event Resumed();

    event StakingPaused();
    event StakingResumed();
    event StakingLimitSet(uint256 maxStakeLimit, uint256 stakeLimitIncreasePerBlock);
    event StakingLimitRemoved();

    /**
      * @notice Set Lido protocol contracts (oracle, treasury, insurance fund).
      * @param _oracle oracle contract
      * @param _treasury treasury contract
      * @param _insuranceFund insurance fund contract
      */
    function setProtocolContracts(
        address _oracle,
        address _treasury,
        address _insuranceFund
    ) external;

    event ProtocolContactsSet(address oracle, address treasury, address insuranceFund);

    /**
      * @notice Set fee rate to `_feeBasisPoints` basis points.
      * The fees are accrued when:
      * - oracles report staking results (beacon chain balance increase)
      * - validators gain execution layer rewards (priority fees and MEV)
      * @param _feeBasisPoints Fee rate, in basis points
      */
    function setFee(uint16 _feeBasisPoints) external;

    /**
      * @notice Set fee distribution
      * @param _treasuryFeeBasisPoints basis points go to the treasury,
      * @param _insuranceFeeBasisPoints basis points go to the insurance fund,
      * @param _operatorsFeeBasisPoints basis points go to node operators.
      * @dev The sum has to be 10 000.
      */
    function setFeeDistribution(
        uint16 _treasuryFeeBasisPoints,
        uint16 _insuranceFeeBasisPoints,
        uint16 _operatorsFeeBasisPoints
    ) external;

    /**
      * @notice Returns staking rewards fee rate
      */
    function getFee() external view returns (uint16 feeBasisPoints);

    /**
      * @notice Returns fee distribution proportion
      */
    function getFeeDistribution() external view returns (
        uint16 treasuryFeeBasisPoints,
        uint16 insuranceFeeBasisPoints,
        uint16 operatorsFeeBasisPoints
    );

    event FeeSet(uint16 feeBasisPoints);

    event FeeDistributionSet(uint16 treasuryFeeBasisPoints, uint16 insuranceFeeBasisPoints, uint16 operatorsFeeBasisPoints);

    /**
      * @notice A payable function supposed to be called only by LidoExecutionLayerRewardsVault contract
      * @dev We need a dedicated function because funds received by the default payable function
      * are treated as a user deposit
      */
    function receiveELRewards() external payable;

    // The amount of ETH withdrawn from LidoExecutionLayerRewardsVault contract to Lido contract
    event ELRewardsReceived(uint256 amount);

    /**
      * @dev Sets limit on amount of ETH to withdraw from execution layer rewards vault per LidoOracle report
      * @param _limitPoints limit in basis points to amount of ETH to withdraw per LidoOracle report
      */
    function setELRewardsWithdrawalLimit(uint16 _limitPoints) external;

    // Percent in basis points of total pooled ether allowed to withdraw from LidoExecutionLayerRewardsVault per LidoOracle report
    event ELRewardsWithdrawalLimitSet(uint256 limitPoints);

    /**
      * @notice Set credentials to withdraw ETH on ETH 2.0 side after the phase 2 is launched to `_withdrawalCredentials`
      * @dev Note that setWithdrawalCredentials discards all unused signing keys as the signatures are invalidated.
      * @param _withdrawalCredentials withdrawal credentials field as defined in the Ethereum PoS consensus specs
      */
    function setWithdrawalCredentials(bytes32 _withdrawalCredentials) external;

    /**
      * @notice Returns current credentials to withdraw ETH on ETH 2.0 side after the phase 2 is launched
      */
    function getWithdrawalCredentials() external view returns (bytes);

    event WithdrawalCredentialsSet(bytes32 withdrawalCredentials);

    /**
      * @dev Sets the address of LidoExecutionLayerRewardsVault contract
      * @param _executionLayerRewardsVault Execution layer rewards vault contract address
      */
    function setELRewardsVault(address _executionLayerRewardsVault) external;

    // The `executionLayerRewardsVault` was set as the execution layer rewards vault for Lido
    event ELRewardsVaultSet(address executionLayerRewardsVault);

    /**
      * @notice Ether on the ETH 2.0 side reported by the oracle
      * @param _epoch Epoch id
      * @param _eth2balance Balance in wei on the ETH 2.0 side
      */
    function handleOracleReport(uint256 _epoch, uint256 _eth2balance) external;


    // User functions

    /**
      * @notice Adds eth to the pool
      * @return StETH Amount of StETH generated
      */
    function submit(address _referral) external payable returns (uint256 StETH);

    // Records a deposit made by a user
    event Submitted(address indexed sender, uint256 amount, address referral);

    // The `amount` of ether was sent to the deposit_contract.deposit function
    event Unbuffered(uint256 amount);

    // Requested withdrawal of `etherAmount` to `pubkeyHash` on the ETH 2.0 side, `tokenAmount` burned by `sender`,
    // `sentFromBuffer` was sent on the current Ethereum side.
    event Withdrawal(address indexed sender, uint256 tokenAmount, uint256 sentFromBuffer,
                     bytes32 indexed pubkeyHash, uint256 etherAmount);


    // Info functions

    /**
      * @notice Gets the amount of Ether controlled by the system
      */
    function getTotalPooledEther() external view returns (uint256);

    /**
      * @notice Gets the amount of Ether temporary buffered on this contract balance
      */
    function getBufferedEther() external view returns (uint256);

    /**
      * @notice Returns the key values related to Beacon-side
      * @return depositedValidators - number of deposited validators
      * @return beaconValidators - number of Lido's validators visible in the Beacon state, reported by oracles
      * @return beaconBalance - total amount of Beacon-side Ether (sum of all the balances of Lido validators)
      */
    function getBeaconStat() external view returns (uint256 depositedValidators, uint256 beaconValidators, uint256 beaconBalance);
}

// SPDX-FileCopyrightText: 2020 Lido <[email protected]>

// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.4.24;


/**
  * @title Node Operator registry
  *
  * Node Operator registry manages signing keys and other node operator data.
  * It's also responsible for distributing rewards to node operators.
  */
interface INodeOperatorsRegistry {
    /**
      * @notice Add node operator named `name` with reward address `rewardAddress` and staking limit = 0 validators
      * @param _name Human-readable name
      * @param _rewardAddress Ethereum 1 address which receives stETH rewards for this operator
      * @return a unique key of the added operator
      */
    function addNodeOperator(string _name, address _rewardAddress) external returns (uint256 id);

    /**
      * @notice `_active ? 'Enable' : 'Disable'` the node operator #`_id`
      */
    function setNodeOperatorActive(uint256 _id, bool _active) external;

    /**
      * @notice Change human-readable name of the node operator #`_id` to `_name`
      */
    function setNodeOperatorName(uint256 _id, string _name) external;

    /**
      * @notice Change reward address of the node operator #`_id` to `_rewardAddress`
      */
    function setNodeOperatorRewardAddress(uint256 _id, address _rewardAddress) external;

    /**
      * @notice Set the maximum number of validators to stake for the node operator #`_id` to `_stakingLimit`
      */
    function setNodeOperatorStakingLimit(uint256 _id, uint64 _stakingLimit) external;

    /**
      * @notice Report `_stoppedIncrement` more stopped validators of the node operator #`_id`
      */
    function reportStoppedValidators(uint256 _id, uint64 _stoppedIncrement) external;

    /**
      * @notice Remove unused signing keys
      * @dev Function is used by the pool
      */
    function trimUnusedKeys() external;

    /**
      * @notice Returns total number of node operators
      */
    function getNodeOperatorsCount() external view returns (uint256);

    /**
      * @notice Returns number of active node operators
      */
    function getActiveNodeOperatorsCount() external view returns (uint256);

    /**
      * @notice Returns the n-th node operator
      * @param _id Node Operator id
      * @param _fullInfo If true, name will be returned as well
      */
    function getNodeOperator(uint256 _id, bool _fullInfo) external view returns (
        bool active,
        string name,
        address rewardAddress,
        uint64 stakingLimit,
        uint64 stoppedValidators,
        uint64 totalSigningKeys,
        uint64 usedSigningKeys);

    /**
      * @notice Returns the rewards distribution proportional to the effective stake for each node operator.
      * @param _totalRewardShares Total amount of reward shares to distribute.
      */
    function getRewardsDistribution(uint256 _totalRewardShares) external view returns (
        address[] memory recipients,
        uint256[] memory shares
    );

    event NodeOperatorAdded(uint256 id, string name, address rewardAddress, uint64 stakingLimit);
    event NodeOperatorActiveSet(uint256 indexed id, bool active);
    event NodeOperatorNameSet(uint256 indexed id, string name);
    event NodeOperatorRewardAddressSet(uint256 indexed id, address rewardAddress);
    event NodeOperatorStakingLimitSet(uint256 indexed id, uint64 stakingLimit);
    event NodeOperatorTotalStoppedValidatorsReported(uint256 indexed id, uint64 totalStopped);
    event NodeOperatorTotalKeysTrimmed(uint256 indexed id, uint64 totalKeysTrimmed);

    /**
     * @notice Selects and returns at most `_numKeys` signing keys (as well as the corresponding
     *         signatures) from the set of active keys and marks the selected keys as used.
     *         May only be called by the pool contract.
     *
     * @param _numKeys The number of keys to select. The actual number of selected keys may be less
     *        due to the lack of active keys.
     */
    function assignNextSigningKeys(uint256 _numKeys) external returns (bytes memory pubkeys, bytes memory signatures);

    /**
      * @notice Add `_quantity` validator signing keys to the keys of the node operator #`_operator_id`. Concatenated keys are: `_pubkeys`
      * @dev Along with each key the DAO has to provide a signatures for the
      *      (pubkey, withdrawal_credentials, 32000000000) message.
      *      Given that information, the contract'll be able to call
      *      deposit_contract.deposit on-chain.
      * @param _operator_id Node Operator id
      * @param _quantity Number of signing keys provided
      * @param _pubkeys Several concatenated validator signing keys
      * @param _signatures Several concatenated signatures for (pubkey, withdrawal_credentials, 32000000000) messages
      */
    function addSigningKeys(uint256 _operator_id, uint256 _quantity, bytes _pubkeys, bytes _signatures) external;

    /**
      * @notice Add `_quantity` validator signing keys of operator #`_id` to the set of usable keys. Concatenated keys are: `_pubkeys`. Can be done by node operator in question by using the designated rewards address.
      * @dev Along with each key the DAO has to provide a signatures for the
      *      (pubkey, withdrawal_credentials, 32000000000) message.
      *      Given that information, the contract'll be able to call
      *      deposit_contract.deposit on-chain.
      * @param _operator_id Node Operator id
      * @param _quantity Number of signing keys provided
      * @param _pubkeys Several concatenated validator signing keys
      * @param _signatures Several concatenated signatures for (pubkey, withdrawal_credentials, 32000000000) messages
      */
    function addSigningKeysOperatorBH(uint256 _operator_id, uint256 _quantity, bytes _pubkeys, bytes _signatures) external;

    /**
      * @notice Removes a validator signing key #`_index` from the keys of the node operator #`_operator_id`
      * @param _operator_id Node Operator id
      * @param _index Index of the key, starting with 0
      */
    function removeSigningKey(uint256 _operator_id, uint256 _index) external;

    /**
      * @notice Removes a validator signing key #`_index` of operator #`_id` from the set of usable keys. Executed on behalf of Node Operator.
      * @param _operator_id Node Operator id
      * @param _index Index of the key, starting with 0
      */
    function removeSigningKeyOperatorBH(uint256 _operator_id, uint256 _index) external;

    /**
      * @notice Removes an #`_amount` of validator signing keys starting from #`_index` of operator #`_id` usable keys. Executed on behalf of DAO.
      * @param _operator_id Node Operator id
      * @param _index Index of the key, starting with 0
      * @param _amount Number of keys to remove
      */
    function removeSigningKeys(uint256 _operator_id, uint256 _index, uint256 _amount) external;

    /**
      * @notice Removes an #`_amount` of validator signing keys starting from #`_index` of operator #`_id` usable keys. Executed on behalf of Node Operator.
      * @param _operator_id Node Operator id
      * @param _index Index of the key, starting with 0
      * @param _amount Number of keys to remove
      */
    function removeSigningKeysOperatorBH(uint256 _operator_id, uint256 _index, uint256 _amount) external;

    /**
      * @notice Returns total number of signing keys of the node operator #`_operator_id`
      */
    function getTotalSigningKeyCount(uint256 _operator_id) external view returns (uint256);

    /**
      * @notice Returns number of usable signing keys of the node operator #`_operator_id`
      */
    function getUnusedSigningKeyCount(uint256 _operator_id) external view returns (uint256);

    /**
      * @notice Returns n-th signing key of the node operator #`_operator_id`
      * @param _operator_id Node Operator id
      * @param _index Index of the key, starting with 0
      * @return key Key
      * @return depositSignature Signature needed for a deposit_contract.deposit call
      * @return used Flag indication if the key was used in the staking
      */
    function getSigningKey(uint256 _operator_id, uint256 _index) external view returns
            (bytes key, bytes depositSignature, bool used);


    /**
     * @notice Returns a monotonically increasing counter that gets incremented when any of the following happens:
     *   1. a node operator's key(s) is added;
     *   2. a node operator's key(s) is removed;
     *   3. a node operator's approved keys limit is changed.
     *   4. a node operator was activated/deactivated. Activation or deactivation of node operator
     *      might lead to usage of unvalidated keys in the assignNextSigningKeys method.
     */
    function getKeysOpIndex() external view returns (uint256);

    event SigningKeyAdded(uint256 indexed operatorId, bytes pubkey);
    event SigningKeyRemoved(uint256 indexed operatorId, bytes pubkey);
    event KeysOpIndexSet(uint256 keysOpIndex);
}

File 8 of 35 : IDepositContract.sol
// SPDX-FileCopyrightText: 2020 Lido <[email protected]>

// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.4.24;


/**
  * @title Deposit contract interface
  */
interface IDepositContract {
    /**
      * @notice Top-ups deposit of a validator on the ETH 2.0 side
      * @param pubkey Validator signing key
      * @param withdrawal_credentials Credentials that allows to withdraw funds
      * @param signature Signature of the request
      * @param deposit_data_root The deposits Merkle tree node, used as a checksum
      */
    function deposit(
        bytes /* 48 */ pubkey,
        bytes /* 32 */ withdrawal_credentials,
        bytes /* 96 */ signature,
        bytes32 deposit_data_root
    )
        external payable;
}

// SPDX-FileCopyrightText: 2021 Lido <[email protected]>

// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.4.24;


interface ILidoExecutionLayerRewardsVault {

    /**
    * @notice Withdraw all accumulated execution layer rewards to Lido contract
    * @param _maxAmount Max amount of ETH to withdraw
    * @return amount of funds received as execution layer rewards (in wei)
    */
    function withdrawRewards(uint256 _maxAmount) external returns (uint256 amount);
}

// SPDX-FileCopyrightText: 2020 Lido <[email protected]>

// SPDX-License-Identifier: GPL-3.0

/* See contracts/COMPILERS.md */
pragma solidity 0.4.24;

import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "@aragon/os/contracts/common/UnstructuredStorage.sol";
import "@aragon/os/contracts/lib/math/SafeMath.sol";
import "./lib/Pausable.sol";

/**
 * @title Interest-bearing ERC20-like token for Lido Liquid Stacking protocol.
 *
 * This contract is abstract. To make the contract deployable override the
 * `_getTotalPooledEther` function. `Lido.sol` contract inherits StETH and defines
 * the `_getTotalPooledEther` function.
 *
 * StETH balances are dynamic and represent the holder's share in the total amount
 * of Ether controlled by the protocol. Account shares aren't normalized, so the
 * contract also stores the sum of all shares to calculate each account's token balance
 * which equals to:
 *
 *   shares[account] * _getTotalPooledEther() / _getTotalShares()
 *
 * For example, assume that we have:
 *
 *   _getTotalPooledEther() -> 10 ETH
 *   sharesOf(user1) -> 100
 *   sharesOf(user2) -> 400
 *
 * Therefore:
 *
 *   balanceOf(user1) -> 2 tokens which corresponds 2 ETH
 *   balanceOf(user2) -> 8 tokens which corresponds 8 ETH
 *
 * Since balances of all token holders change when the amount of total pooled Ether
 * changes, this token cannot fully implement ERC20 standard: it only emits `Transfer`
 * events upon explicit transfer between holders. In contrast, when total amount of
 * pooled Ether increases, no `Transfer` events are generated: doing so would require
 * emitting an event for each token holder and thus running an unbounded loop.
 *
 * The token inherits from `Pausable` and uses `whenNotStopped` modifier for methods
 * which change `shares` or `allowances`. `_stop` and `_resume` functions are overridden
 * in `Lido.sol` and might be called by an account with the `PAUSE_ROLE` assigned by the
 * DAO. This is useful for emergency scenarios, e.g. a protocol bug, where one might want
 * to freeze all token transfers and approvals until the emergency is resolved.
 */
contract StETH is IERC20, Pausable {
    using SafeMath for uint256;
    using UnstructuredStorage for bytes32;

    /**
     * @dev StETH balances are dynamic and are calculated based on the accounts' shares
     * and the total amount of Ether controlled by the protocol. Account shares aren't
     * normalized, so the contract also stores the sum of all shares to calculate
     * each account's token balance which equals to:
     *
     *   shares[account] * _getTotalPooledEther() / _getTotalShares()
    */
    mapping (address => uint256) private shares;

    /**
     * @dev Allowances are nominated in tokens, not token shares.
     */
    mapping (address => mapping (address => uint256)) private allowances;

    /**
     * @dev Storage position used for holding the total amount of shares in existence.
     *
     * The Lido protocol is built on top of Aragon and uses the Unstructured Storage pattern
     * for value types:
     *
     * https://blog.openzeppelin.com/upgradeability-using-unstructured-storage
     * https://blog.8bitzen.com/posts/20-02-2020-understanding-how-solidity-upgradeable-unstructured-proxies-work
     *
     * For reference types, conventional storage variables are used since it's non-trivial
     * and error-prone to implement reference-type unstructured storage using Solidity v0.4;
     * see https://github.com/lidofinance/lido-dao/issues/181#issuecomment-736098834
     */
    bytes32 internal constant TOTAL_SHARES_POSITION = keccak256("lido.StETH.totalShares");

    /**
      * @notice An executed shares transfer from `sender` to `recipient`.
      *
      * @dev emitted in pair with an ERC20-defined `Transfer` event.
      */
    event TransferShares(
        address indexed from,
        address indexed to,
        uint256 sharesValue
    );

    /**
     * @notice An executed `burnShares` request
     *
     * @dev Reports simultaneously burnt shares amount
     * and corresponding stETH amount.
     * The stETH amount is calculated twice: before and after the burning incurred rebase.
     *
     * @param account holder of the burnt shares
     * @param preRebaseTokenAmount amount of stETH the burnt shares corresponded to before the burn
     * @param postRebaseTokenAmount amount of stETH the burnt shares corresponded to after the burn
     * @param sharesAmount amount of burnt shares
     */
    event SharesBurnt(
        address indexed account,
        uint256 preRebaseTokenAmount,
        uint256 postRebaseTokenAmount,
        uint256 sharesAmount
    );

    /**
     * @return the name of the token.
     */
    function name() public pure returns (string) {
        return "Liquid staked Ether 2.0";
    }

    /**
     * @return the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public pure returns (string) {
        return "stETH";
    }

    /**
     * @return the number of decimals for getting user representation of a token amount.
     */
    function decimals() public pure returns (uint8) {
        return 18;
    }

    /**
     * @return the amount of tokens in existence.
     *
     * @dev Always equals to `_getTotalPooledEther()` since token amount
     * is pegged to the total amount of Ether controlled by the protocol.
     */
    function totalSupply() public view returns (uint256) {
        return _getTotalPooledEther();
    }

    /**
     * @return the entire amount of Ether controlled by the protocol.
     *
     * @dev The sum of all ETH balances in the protocol, equals to the total supply of stETH.
     */
    function getTotalPooledEther() public view returns (uint256) {
        return _getTotalPooledEther();
    }

    /**
     * @return the amount of tokens owned by the `_account`.
     *
     * @dev Balances are dynamic and equal the `_account`'s share in the amount of the
     * total Ether controlled by the protocol. See `sharesOf`.
     */
    function balanceOf(address _account) public view returns (uint256) {
        return getPooledEthByShares(_sharesOf(_account));
    }

    /**
     * @notice Moves `_amount` tokens from the caller's account to the `_recipient` account.
     *
     * @return a boolean value indicating whether the operation succeeded.
     * Emits a `Transfer` event.
     * Emits a `TransferShares` event.
     *
     * Requirements:
     *
     * - `_recipient` cannot be the zero address.
     * - the caller must have a balance of at least `_amount`.
     * - the contract must not be paused.
     *
     * @dev The `_amount` argument is the amount of tokens, not shares.
     */
    function transfer(address _recipient, uint256 _amount) public returns (bool) {
        _transfer(msg.sender, _recipient, _amount);
        return true;
    }

    /**
     * @return the remaining number of tokens that `_spender` is allowed to spend
     * on behalf of `_owner` through `transferFrom`. This is zero by default.
     *
     * @dev This value changes when `approve` or `transferFrom` is called.
     */
    function allowance(address _owner, address _spender) public view returns (uint256) {
        return allowances[_owner][_spender];
    }

    /**
     * @notice Sets `_amount` as the allowance of `_spender` over the caller's tokens.
     *
     * @return a boolean value indicating whether the operation succeeded.
     * Emits an `Approval` event.
     *
     * Requirements:
     *
     * - `_spender` cannot be the zero address.
     * - the contract must not be paused.
     *
     * @dev The `_amount` argument is the amount of tokens, not shares.
     */
    function approve(address _spender, uint256 _amount) public returns (bool) {
        _approve(msg.sender, _spender, _amount);
        return true;
    }

    /**
     * @notice Moves `_amount` tokens from `_sender` to `_recipient` using the
     * allowance mechanism. `_amount` is then deducted from the caller's
     * allowance.
     *
     * @return a boolean value indicating whether the operation succeeded.
     *
     * Emits a `Transfer` event.
     * Emits a `TransferShares` event.
     * Emits an `Approval` event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `_sender` and `_recipient` cannot be the zero addresses.
     * - `_sender` must have a balance of at least `_amount`.
     * - the caller must have allowance for `_sender`'s tokens of at least `_amount`.
     * - the contract must not be paused.
     *
     * @dev The `_amount` argument is the amount of tokens, not shares.
     */
    function transferFrom(address _sender, address _recipient, uint256 _amount) public returns (bool) {
        uint256 currentAllowance = allowances[_sender][msg.sender];
        require(currentAllowance >= _amount, "TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE");

        _transfer(_sender, _recipient, _amount);
        _approve(_sender, msg.sender, currentAllowance.sub(_amount));
        return true;
    }

    /**
     * @notice Atomically increases the allowance granted to `_spender` by the caller by `_addedValue`.
     *
     * This is an alternative to `approve` that can be used as a mitigation for
     * problems described in:
     * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol#L42
     * Emits an `Approval` event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `_spender` cannot be the the zero address.
     * - the contract must not be paused.
     */
    function increaseAllowance(address _spender, uint256 _addedValue) public returns (bool) {
        _approve(msg.sender, _spender, allowances[msg.sender][_spender].add(_addedValue));
        return true;
    }

    /**
     * @notice Atomically decreases the allowance granted to `_spender` by the caller by `_subtractedValue`.
     *
     * This is an alternative to `approve` that can be used as a mitigation for
     * problems described in:
     * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol#L42
     * Emits an `Approval` event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `_spender` cannot be the zero address.
     * - `_spender` must have allowance for the caller of at least `_subtractedValue`.
     * - the contract must not be paused.
     */
    function decreaseAllowance(address _spender, uint256 _subtractedValue) public returns (bool) {
        uint256 currentAllowance = allowances[msg.sender][_spender];
        require(currentAllowance >= _subtractedValue, "DECREASED_ALLOWANCE_BELOW_ZERO");
        _approve(msg.sender, _spender, currentAllowance.sub(_subtractedValue));
        return true;
    }

    /**
     * @return the total amount of shares in existence.
     *
     * @dev The sum of all accounts' shares can be an arbitrary number, therefore
     * it is necessary to store it in order to calculate each account's relative share.
     */
    function getTotalShares() public view returns (uint256) {
        return _getTotalShares();
    }

    /**
     * @return the amount of shares owned by `_account`.
     */
    function sharesOf(address _account) public view returns (uint256) {
        return _sharesOf(_account);
    }

    /**
     * @return the amount of shares that corresponds to `_ethAmount` protocol-controlled Ether.
     */
    function getSharesByPooledEth(uint256 _ethAmount) public view returns (uint256) {
        uint256 totalPooledEther = _getTotalPooledEther();
        if (totalPooledEther == 0) {
            return 0;
        } else {
            return _ethAmount
                .mul(_getTotalShares())
                .div(totalPooledEther);
        }
    }

    /**
     * @return the amount of Ether that corresponds to `_sharesAmount` token shares.
     */
    function getPooledEthByShares(uint256 _sharesAmount) public view returns (uint256) {
        uint256 totalShares = _getTotalShares();
        if (totalShares == 0) {
            return 0;
        } else {
            return _sharesAmount
                .mul(_getTotalPooledEther())
                .div(totalShares);
        }
    }

    /**
     * @notice Moves `_sharesAmount` token shares from the caller's account to the `_recipient` account.
     *
     * @return amount of transferred tokens.
     * Emits a `TransferShares` event.
     * Emits a `Transfer` event.
     *
     * Requirements:
     *
     * - `_recipient` cannot be the zero address.
     * - the caller must have at least `_sharesAmount` shares.
     * - the contract must not be paused.
     *
     * @dev The `_sharesAmount` argument is the amount of shares, not tokens.
     */
    function transferShares(address _recipient, uint256 _sharesAmount) public returns (uint256) {
        _transferShares(msg.sender, _recipient, _sharesAmount);
        emit TransferShares(msg.sender, _recipient, _sharesAmount);
        uint256 tokensAmount = getPooledEthByShares(_sharesAmount);
        emit Transfer(msg.sender, _recipient, tokensAmount);
        return tokensAmount;
    }

    /**
     * @return the total amount (in wei) of Ether controlled by the protocol.
     * @dev This is used for calculating tokens from shares and vice versa.
     * @dev This function is required to be implemented in a derived contract.
     */
    function _getTotalPooledEther() internal view returns (uint256);

    /**
     * @notice Moves `_amount` tokens from `_sender` to `_recipient`.
     * Emits a `Transfer` event.
     * Emits a `TransferShares` event.
     */
    function _transfer(address _sender, address _recipient, uint256 _amount) internal {
        uint256 _sharesToTransfer = getSharesByPooledEth(_amount);
        _transferShares(_sender, _recipient, _sharesToTransfer);
        emit Transfer(_sender, _recipient, _amount);
        emit TransferShares(_sender, _recipient, _sharesToTransfer);
    }

    /**
     * @notice Sets `_amount` as the allowance of `_spender` over the `_owner` s tokens.
     *
     * Emits an `Approval` event.
     *
     * Requirements:
     *
     * - `_owner` cannot be the zero address.
     * - `_spender` cannot be the zero address.
     * - the contract must not be paused.
     */
    function _approve(address _owner, address _spender, uint256 _amount) internal whenNotStopped {
        require(_owner != address(0), "APPROVE_FROM_ZERO_ADDRESS");
        require(_spender != address(0), "APPROVE_TO_ZERO_ADDRESS");

        allowances[_owner][_spender] = _amount;
        emit Approval(_owner, _spender, _amount);
    }

    /**
     * @return the total amount of shares in existence.
     */
    function _getTotalShares() internal view returns (uint256) {
        return TOTAL_SHARES_POSITION.getStorageUint256();
    }

    /**
     * @return the amount of shares owned by `_account`.
     */
    function _sharesOf(address _account) internal view returns (uint256) {
        return shares[_account];
    }

    /**
     * @notice Moves `_sharesAmount` shares from `_sender` to `_recipient`.
     *
     * Requirements:
     *
     * - `_sender` cannot be the zero address.
     * - `_recipient` cannot be the zero address.
     * - `_sender` must hold at least `_sharesAmount` shares.
     * - the contract must not be paused.
     */
    function _transferShares(address _sender, address _recipient, uint256 _sharesAmount) internal whenNotStopped {
        require(_sender != address(0), "TRANSFER_FROM_THE_ZERO_ADDRESS");
        require(_recipient != address(0), "TRANSFER_TO_THE_ZERO_ADDRESS");

        uint256 currentSenderShares = shares[_sender];
        require(_sharesAmount <= currentSenderShares, "TRANSFER_AMOUNT_EXCEEDS_BALANCE");

        shares[_sender] = currentSenderShares.sub(_sharesAmount);
        shares[_recipient] = shares[_recipient].add(_sharesAmount);
    }

    /**
     * @notice Creates `_sharesAmount` shares and assigns them to `_recipient`, increasing the total amount of shares.
     * @dev This doesn't increase the token total supply.
     *
     * Requirements:
     *
     * - `_recipient` cannot be the zero address.
     * - the contract must not be paused.
     */
    function _mintShares(address _recipient, uint256 _sharesAmount) internal whenNotStopped returns (uint256 newTotalShares) {
        require(_recipient != address(0), "MINT_TO_THE_ZERO_ADDRESS");

        newTotalShares = _getTotalShares().add(_sharesAmount);
        TOTAL_SHARES_POSITION.setStorageUint256(newTotalShares);

        shares[_recipient] = shares[_recipient].add(_sharesAmount);

        // Notice: we're not emitting a Transfer event from the zero address here since shares mint
        // works by taking the amount of tokens corresponding to the minted shares from all other
        // token holders, proportionally to their share. The total supply of the token doesn't change
        // as the result. This is equivalent to performing a send from each other token holder's
        // address to `address`, but we cannot reflect this as it would require sending an unbounded
        // number of events.
    }

    /**
     * @notice Destroys `_sharesAmount` shares from `_account`'s holdings, decreasing the total amount of shares.
     * @dev This doesn't decrease the token total supply.
     *
     * Requirements:
     *
     * - `_account` cannot be the zero address.
     * - `_account` must hold at least `_sharesAmount` shares.
     * - the contract must not be paused.
     */
    function _burnShares(address _account, uint256 _sharesAmount) internal whenNotStopped returns (uint256 newTotalShares) {
        require(_account != address(0), "BURN_FROM_THE_ZERO_ADDRESS");

        uint256 accountShares = shares[_account];
        require(_sharesAmount <= accountShares, "BURN_AMOUNT_EXCEEDS_BALANCE");

        uint256 preRebaseTokenAmount = getPooledEthByShares(_sharesAmount);

        newTotalShares = _getTotalShares().sub(_sharesAmount);
        TOTAL_SHARES_POSITION.setStorageUint256(newTotalShares);

        shares[_account] = accountShares.sub(_sharesAmount);

        uint256 postRebaseTokenAmount = getPooledEthByShares(_sharesAmount);

        emit SharesBurnt(_account, preRebaseTokenAmount, postRebaseTokenAmount, _sharesAmount);

        // Notice: we're not emitting a Transfer event to the zero address here since shares burn
        // works by redistributing the amount of tokens corresponding to the burned shares between
        // all other token holders. The total supply of the token doesn't change as the result.
        // This is equivalent to performing a send from `address` to each other token holder address,
        // but we cannot reflect this as it would require sending an unbounded number of events.

        // We're emitting `SharesBurnt` event to provide an explicit rebase log record nonetheless.
    }
}

// SPDX-FileCopyrightText: 2022 Lido <[email protected]>

// SPDX-License-Identifier: GPL-3.0

/* See contracts/COMPILERS.md */
pragma solidity 0.4.24;

import "@aragon/os/contracts/common/UnstructuredStorage.sol";

//
// We need to pack four variables into the same 256bit-wide storage slot
// to lower the costs per each staking request.
//
// As a result, slot's memory aligned as follows:
//
// MSB ------------------------------------------------------------------------------> LSB
// 256____________160_________________________128_______________32_____________________ 0
// |_______________|___________________________|________________|_______________________|
// | maxStakeLimit | maxStakeLimitGrowthBlocks | prevStakeLimit | prevStakeBlockNumber  |
// |<-- 96 bits -->|<---------- 32 bits ------>|<-- 96 bits --->|<----- 32 bits ------->|
//
//
// NB: Internal representation conventions:
//
// - the `maxStakeLimitGrowthBlocks` field above represented as follows:
// `maxStakeLimitGrowthBlocks` = `maxStakeLimit` / `stakeLimitIncreasePerBlock`
//           32 bits                 96 bits               96 bits
//
//
// - the "staking paused" state is encoded by `prevStakeBlockNumber` being zero,
// - the "staking unlimited" state is encoded by `maxStakeLimit` being zero and `prevStakeBlockNumber` being non-zero.
//

/**
* @notice Library for the internal structs definitions
* @dev solidity <0.6 doesn't support top-level structs
* using the library to have a proper namespace
*/
library StakeLimitState {
    /**
      * @dev Internal representation struct (slot-wide)
      */
    struct Data {
        uint32 prevStakeBlockNumber;
        uint96 prevStakeLimit;
        uint32 maxStakeLimitGrowthBlocks;
        uint96 maxStakeLimit;
    }
}

library StakeLimitUnstructuredStorage {
    using UnstructuredStorage for bytes32;

    /// @dev Storage offset for `maxStakeLimit` (bits)
    uint256 internal constant MAX_STAKE_LIMIT_OFFSET = 160;
    /// @dev Storage offset for `maxStakeLimitGrowthBlocks` (bits)
    uint256 internal constant MAX_STAKE_LIMIT_GROWTH_BLOCKS_OFFSET = 128;
    /// @dev Storage offset for `prevStakeLimit` (bits)
    uint256 internal constant PREV_STAKE_LIMIT_OFFSET = 32;
    /// @dev Storage offset for `prevStakeBlockNumber` (bits)
    uint256 internal constant PREV_STAKE_BLOCK_NUMBER_OFFSET = 0;

    /**
    * @dev Read stake limit state from the unstructured storage position
    * @param _position storage offset
    */
    function getStorageStakeLimitStruct(bytes32 _position) internal view returns (StakeLimitState.Data memory stakeLimit) {
        uint256 slotValue = _position.getStorageUint256();

        stakeLimit.prevStakeBlockNumber = uint32(slotValue >> PREV_STAKE_BLOCK_NUMBER_OFFSET);
        stakeLimit.prevStakeLimit = uint96(slotValue >> PREV_STAKE_LIMIT_OFFSET);
        stakeLimit.maxStakeLimitGrowthBlocks = uint32(slotValue >> MAX_STAKE_LIMIT_GROWTH_BLOCKS_OFFSET);
        stakeLimit.maxStakeLimit = uint96(slotValue >> MAX_STAKE_LIMIT_OFFSET);
    }

     /**
    * @dev Write stake limit state to the unstructured storage position
    * @param _position storage offset
    * @param _data stake limit state structure instance
    */
    function setStorageStakeLimitStruct(bytes32 _position, StakeLimitState.Data memory _data) internal {
        _position.setStorageUint256(
            uint256(_data.prevStakeBlockNumber) << PREV_STAKE_BLOCK_NUMBER_OFFSET
                | uint256(_data.prevStakeLimit) << PREV_STAKE_LIMIT_OFFSET
                | uint256(_data.maxStakeLimitGrowthBlocks) << MAX_STAKE_LIMIT_GROWTH_BLOCKS_OFFSET
                | uint256(_data.maxStakeLimit) << MAX_STAKE_LIMIT_OFFSET
        );
    }
}

/**
* @notice Interface library with helper functions to deal with stake limit struct in a more high-level approach.
*/
library StakeLimitUtils {
    /**
    * @notice Calculate stake limit for the current block.
    */
    function calculateCurrentStakeLimit(StakeLimitState.Data memory _data) internal view returns(uint256 limit) {
        uint256 stakeLimitIncPerBlock;
        if (_data.maxStakeLimitGrowthBlocks != 0) {
            stakeLimitIncPerBlock = _data.maxStakeLimit / _data.maxStakeLimitGrowthBlocks;
        }

        limit = _data.prevStakeLimit + ((block.number - _data.prevStakeBlockNumber) * stakeLimitIncPerBlock);
        if (limit > _data.maxStakeLimit) {
            limit = _data.maxStakeLimit;
        }
    }

    /**
    * @notice check if staking is on pause
    */
    function isStakingPaused(StakeLimitState.Data memory _data) internal pure returns(bool) {
        return _data.prevStakeBlockNumber == 0;
    }

    /**
    * @notice check if staking limit is set (otherwise staking is unlimited)
    */
    function isStakingLimitSet(StakeLimitState.Data memory _data) internal pure returns(bool) {
        return _data.maxStakeLimit != 0;
    }

    /**
    * @notice update stake limit repr with the desired limits
    * @dev input `_data` param is mutated and the func returns effectively the same pointer
    * @param _data stake limit state struct
    * @param _maxStakeLimit stake limit max value
    * @param _stakeLimitIncreasePerBlock stake limit increase (restoration) per block
    */
    function setStakingLimit(
        StakeLimitState.Data memory _data,
        uint256 _maxStakeLimit,
        uint256 _stakeLimitIncreasePerBlock
    ) internal view returns (StakeLimitState.Data memory) {
        require(_maxStakeLimit != 0, "ZERO_MAX_STAKE_LIMIT");
        require(_maxStakeLimit <= uint96(-1), "TOO_LARGE_MAX_STAKE_LIMIT");
        require(_maxStakeLimit >= _stakeLimitIncreasePerBlock, "TOO_LARGE_LIMIT_INCREASE");
        require(
            (_stakeLimitIncreasePerBlock == 0)
            || (_maxStakeLimit / _stakeLimitIncreasePerBlock <= uint32(-1)),
            "TOO_SMALL_LIMIT_INCREASE"
        );

        // if staking was paused or unlimited previously,
        // or new limit is lower than previous, then
        // reset prev stake limit to the new max stake limit
        if ((_data.maxStakeLimit == 0) || (_maxStakeLimit < _data.prevStakeLimit)) {
            _data.prevStakeLimit = uint96(_maxStakeLimit);
        }
        _data.maxStakeLimitGrowthBlocks = _stakeLimitIncreasePerBlock != 0 ? uint32(_maxStakeLimit / _stakeLimitIncreasePerBlock) : 0;

        _data.maxStakeLimit = uint96(_maxStakeLimit);

        if (_data.prevStakeBlockNumber != 0) {
            _data.prevStakeBlockNumber = uint32(block.number);
        }

        return _data;
    }

    /**
    * @notice update stake limit repr to remove the limit
    * @dev input `_data` param is mutated and the func returns effectively the same pointer
    * @param _data stake limit state struct
    */
    function removeStakingLimit(
        StakeLimitState.Data memory _data
    ) internal view returns (StakeLimitState.Data memory) {
        _data.maxStakeLimit = 0;

        return _data;
    }

    /**
    * @notice update stake limit repr after submitting user's eth
    * @dev input `_data` param is mutated and the func returns effectively the same pointer
    * @param _data stake limit state struct
    * @param _newPrevStakeLimit new value for the `prevStakeLimit` field
    */
    function updatePrevStakeLimit(
        StakeLimitState.Data memory _data,
        uint256 _newPrevStakeLimit
    ) internal view returns (StakeLimitState.Data memory) {
        assert(_newPrevStakeLimit <= uint96(-1));
        assert(_data.prevStakeBlockNumber != 0);

        _data.prevStakeLimit = uint96(_newPrevStakeLimit);
        _data.prevStakeBlockNumber = uint32(block.number);

        return _data;
    }

    /**
    * @notice set stake limit pause state (on or off)
    * @dev input `_data` param is mutated and the func returns effectively the same pointer
    * @param _data stake limit state struct
    * @param _isPaused pause state flag
    */
    function setStakeLimitPauseState(
        StakeLimitState.Data memory _data,
        bool _isPaused
    ) internal view returns (StakeLimitState.Data memory) {
        _data.prevStakeBlockNumber = uint32(_isPaused ? 0 : block.number);

        return _data;
    }
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;

import "../common/UnstructuredStorage.sol";
import "../kernel/IKernel.sol";


contract AppStorage {
    using UnstructuredStorage for bytes32;

    /* Hardcoded constants to save gas
    bytes32 internal constant KERNEL_POSITION = keccak256("aragonOS.appStorage.kernel");
    bytes32 internal constant APP_ID_POSITION = keccak256("aragonOS.appStorage.appId");
    */
    bytes32 internal constant KERNEL_POSITION = 0x4172f0f7d2289153072b0a6ca36959e0cbe2efc3afe50fc81636caa96338137b;
    bytes32 internal constant APP_ID_POSITION = 0xd625496217aa6a3453eecb9c3489dc5a53e6c67b444329ea2b2cbc9ff547639b;

    function kernel() public view returns (IKernel) {
        return IKernel(KERNEL_POSITION.getStorageAddress());
    }

    function appId() public view returns (bytes32) {
        return APP_ID_POSITION.getStorageBytes32();
    }

    function setKernel(IKernel _kernel) internal {
        KERNEL_POSITION.setStorageAddress(address(_kernel));
    }

    function setAppId(bytes32 _appId) internal {
        APP_ID_POSITION.setStorageBytes32(_appId);
    }
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;


contract ACLSyntaxSugar {
    function arr() internal pure returns (uint256[]) {
        return new uint256[](0);
    }

    function arr(bytes32 _a) internal pure returns (uint256[] r) {
        return arr(uint256(_a));
    }

    function arr(bytes32 _a, bytes32 _b) internal pure returns (uint256[] r) {
        return arr(uint256(_a), uint256(_b));
    }

    function arr(address _a) internal pure returns (uint256[] r) {
        return arr(uint256(_a));
    }

    function arr(address _a, address _b) internal pure returns (uint256[] r) {
        return arr(uint256(_a), uint256(_b));
    }

    function arr(address _a, uint256 _b, uint256 _c) internal pure returns (uint256[] r) {
        return arr(uint256(_a), _b, _c);
    }

    function arr(address _a, uint256 _b, uint256 _c, uint256 _d) internal pure returns (uint256[] r) {
        return arr(uint256(_a), _b, _c, _d);
    }

    function arr(address _a, uint256 _b) internal pure returns (uint256[] r) {
        return arr(uint256(_a), uint256(_b));
    }

    function arr(address _a, address _b, uint256 _c, uint256 _d, uint256 _e) internal pure returns (uint256[] r) {
        return arr(uint256(_a), uint256(_b), _c, _d, _e);
    }

    function arr(address _a, address _b, address _c) internal pure returns (uint256[] r) {
        return arr(uint256(_a), uint256(_b), uint256(_c));
    }

    function arr(address _a, address _b, uint256 _c) internal pure returns (uint256[] r) {
        return arr(uint256(_a), uint256(_b), uint256(_c));
    }

    function arr(uint256 _a) internal pure returns (uint256[] r) {
        r = new uint256[](1);
        r[0] = _a;
    }

    function arr(uint256 _a, uint256 _b) internal pure returns (uint256[] r) {
        r = new uint256[](2);
        r[0] = _a;
        r[1] = _b;
    }

    function arr(uint256 _a, uint256 _b, uint256 _c) internal pure returns (uint256[] r) {
        r = new uint256[](3);
        r[0] = _a;
        r[1] = _b;
        r[2] = _c;
    }

    function arr(uint256 _a, uint256 _b, uint256 _c, uint256 _d) internal pure returns (uint256[] r) {
        r = new uint256[](4);
        r[0] = _a;
        r[1] = _b;
        r[2] = _c;
        r[3] = _d;
    }

    function arr(uint256 _a, uint256 _b, uint256 _c, uint256 _d, uint256 _e) internal pure returns (uint256[] r) {
        r = new uint256[](5);
        r[0] = _a;
        r[1] = _b;
        r[2] = _c;
        r[3] = _d;
        r[4] = _e;
    }
}


contract ACLHelpers {
    function decodeParamOp(uint256 _x) internal pure returns (uint8 b) {
        return uint8(_x >> (8 * 30));
    }

    function decodeParamId(uint256 _x) internal pure returns (uint8 b) {
        return uint8(_x >> (8 * 31));
    }

    function decodeParamsList(uint256 _x) internal pure returns (uint32 a, uint32 b, uint32 c) {
        a = uint32(_x);
        b = uint32(_x >> (8 * 4));
        c = uint32(_x >> (8 * 8));
    }
}

File 14 of 35 : Autopetrified.sol
/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;

import "./Petrifiable.sol";


contract Autopetrified is Petrifiable {
    constructor() public {
        // Immediately petrify base (non-proxy) instances of inherited contracts on deploy.
        // This renders them uninitializable (and unusable without a proxy).
        petrify();
    }
}

pragma solidity ^0.4.24;


library ConversionHelpers {
    string private constant ERROR_IMPROPER_LENGTH = "CONVERSION_IMPROPER_LENGTH";

    function dangerouslyCastUintArrayToBytes(uint256[] memory _input) internal pure returns (bytes memory output) {
        // Force cast the uint256[] into a bytes array, by overwriting its length
        // Note that the bytes array doesn't need to be initialized as we immediately overwrite it
        // with the input and a new length. The input becomes invalid from this point forward.
        uint256 byteLength = _input.length * 32;
        assembly {
            output := _input
            mstore(output, byteLength)
        }
    }

    function dangerouslyCastBytesToUintArray(bytes memory _input) internal pure returns (uint256[] memory output) {
        // Force cast the bytes array into a uint256[], by overwriting its length
        // Note that the uint256[] doesn't need to be initialized as we immediately overwrite it
        // with the input and a new length. The input becomes invalid from this point forward.
        uint256 intsLength = _input.length / 32;
        require(_input.length == intsLength * 32, ERROR_IMPROPER_LENGTH);

        assembly {
            output := _input
            mstore(output, intsLength)
        }
    }
}

File 16 of 35 : ReentrancyGuard.sol
/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;

import "../common/UnstructuredStorage.sol";


contract ReentrancyGuard {
    using UnstructuredStorage for bytes32;

    /* Hardcoded constants to save gas
    bytes32 internal constant REENTRANCY_MUTEX_POSITION = keccak256("aragonOS.reentrancyGuard.mutex");
    */
    bytes32 private constant REENTRANCY_MUTEX_POSITION = 0xe855346402235fdd185c890e68d2c4ecad599b88587635ee285bce2fda58dacb;

    string private constant ERROR_REENTRANT = "REENTRANCY_REENTRANT_CALL";

    modifier nonReentrant() {
        // Ensure mutex is unlocked
        require(!REENTRANCY_MUTEX_POSITION.getStorageBool(), ERROR_REENTRANT);

        // Lock mutex before function call
        REENTRANCY_MUTEX_POSITION.setStorageBool(true);

        // Perform function call
        _;

        // Unlock mutex after function call
        REENTRANCY_MUTEX_POSITION.setStorageBool(false);
    }
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;

import "../lib/token/ERC20.sol";
import "./EtherTokenConstant.sol";
import "./IsContract.sol";
import "./IVaultRecoverable.sol";
import "./SafeERC20.sol";


contract VaultRecoverable is IVaultRecoverable, EtherTokenConstant, IsContract {
    using SafeERC20 for ERC20;

    string private constant ERROR_DISALLOWED = "RECOVER_DISALLOWED";
    string private constant ERROR_VAULT_NOT_CONTRACT = "RECOVER_VAULT_NOT_CONTRACT";
    string private constant ERROR_TOKEN_TRANSFER_FAILED = "RECOVER_TOKEN_TRANSFER_FAILED";

    /**
     * @notice Send funds to recovery Vault. This contract should never receive funds,
     *         but in case it does, this function allows one to recover them.
     * @param _token Token balance to be sent to recovery vault.
     */
    function transferToVault(address _token) external {
        require(allowRecoverability(_token), ERROR_DISALLOWED);
        address vault = getRecoveryVault();
        require(isContract(vault), ERROR_VAULT_NOT_CONTRACT);

        uint256 balance;
        if (_token == ETH) {
            balance = address(this).balance;
            vault.transfer(balance);
        } else {
            ERC20 token = ERC20(_token);
            balance = token.staticBalanceOf(this);
            require(token.safeTransfer(vault, balance), ERROR_TOKEN_TRANSFER_FAILED);
        }

        emit RecoverToVault(vault, _token, balance);
    }

    /**
    * @dev By default deriving from AragonApp makes it recoverable
    * @param token Token address that would be recovered
    * @return bool whether the app allows the recovery
    */
    function allowRecoverability(address token) public view returns (bool) {
        return true;
    }

    // Cast non-implemented interface to be public so we can use it internally
    function getRecoveryVault() public view returns (address);
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;

import "./IEVMScriptExecutor.sol";
import "./IEVMScriptRegistry.sol";

import "../apps/AppStorage.sol";
import "../kernel/KernelConstants.sol";
import "../common/Initializable.sol";


contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelNamespaceConstants {
    string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE";
    string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED";

    /* This is manually crafted in assembly
    string private constant ERROR_EXECUTOR_INVALID_RETURN = "EVMRUN_EXECUTOR_INVALID_RETURN";
    */

    event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData);

    function getEVMScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) {
        return IEVMScriptExecutor(getEVMScriptRegistry().getScriptExecutor(_script));
    }

    function getEVMScriptRegistry() public view returns (IEVMScriptRegistry) {
        address registryAddr = kernel().getApp(KERNEL_APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID);
        return IEVMScriptRegistry(registryAddr);
    }

    function runScript(bytes _script, bytes _input, address[] _blacklist)
        internal
        isInitialized
        protectState
        returns (bytes)
    {
        IEVMScriptExecutor executor = getEVMScriptExecutor(_script);
        require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE);

        bytes4 sig = executor.execScript.selector;
        bytes memory data = abi.encodeWithSelector(sig, _script, _input, _blacklist);

        bytes memory output;
        assembly {
            let success := delegatecall(
                gas,                // forward all gas
                executor,           // address
                add(data, 0x20),    // calldata start
                mload(data),        // calldata length
                0,                  // don't write output (we'll handle this ourselves)
                0                   // don't write output
            )

            output := mload(0x40) // free mem ptr get

            switch success
            case 0 {
                // If the call errored, forward its full error data
                returndatacopy(output, 0, returndatasize)
                revert(output, returndatasize)
            }
            default {
                switch gt(returndatasize, 0x3f)
                case 0 {
                    // Need at least 0x40 bytes returned for properly ABI-encoded bytes values,
                    // revert with "EVMRUN_EXECUTOR_INVALID_RETURN"
                    // See remix: doing a `revert("EVMRUN_EXECUTOR_INVALID_RETURN")` always results in
                    // this memory layout
                    mstore(output, 0x08c379a000000000000000000000000000000000000000000000000000000000)         // error identifier
                    mstore(add(output, 0x04), 0x0000000000000000000000000000000000000000000000000000000000000020) // starting offset
                    mstore(add(output, 0x24), 0x000000000000000000000000000000000000000000000000000000000000001e) // reason length
                    mstore(add(output, 0x44), 0x45564d52554e5f4558454355544f525f494e56414c49445f52455455524e0000) // reason

                    revert(output, 100) // 100 = 4 + 3 * 32 (error identifier + 3 words for the ABI encoded error)
                }
                default {
                    // Copy result
                    //
                    // Needs to perform an ABI decode for the expected `bytes` return type of
                    // `executor.execScript()` as solidity will automatically ABI encode the returned bytes as:
                    //    [ position of the first dynamic length return value = 0x20 (32 bytes) ]
                    //    [ output length (32 bytes) ]
                    //    [ output content (N bytes) ]
                    //
                    // Perform the ABI decode by ignoring the first 32 bytes of the return data
                    let copysize := sub(returndatasize, 0x20)
                    returndatacopy(output, 0x20, copysize)

                    mstore(0x40, add(output, copysize)) // free mem ptr set
                }
            }
        }

        emit ScriptResult(address(executor), _script, _input, output);

        return output;
    }

    modifier protectState {
        address preKernel = address(kernel());
        bytes32 preAppId = appId();
        _; // exec
        require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED);
        require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED);
    }
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;


library UnstructuredStorage {
    function getStorageBool(bytes32 position) internal view returns (bool data) {
        assembly { data := sload(position) }
    }

    function getStorageAddress(bytes32 position) internal view returns (address data) {
        assembly { data := sload(position) }
    }

    function getStorageBytes32(bytes32 position) internal view returns (bytes32 data) {
        assembly { data := sload(position) }
    }

    function getStorageUint256(bytes32 position) internal view returns (uint256 data) {
        assembly { data := sload(position) }
    }

    function setStorageBool(bytes32 position, bool data) internal {
        assembly { sstore(position, data) }
    }

    function setStorageAddress(bytes32 position, address data) internal {
        assembly { sstore(position, data) }
    }

    function setStorageBytes32(bytes32 position, bytes32 data) internal {
        assembly { sstore(position, data) }
    }

    function setStorageUint256(bytes32 position, uint256 data) internal {
        assembly { sstore(position, data) }
    }
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;

import "../acl/IACL.sol";
import "../common/IVaultRecoverable.sol";


interface IKernelEvents {
    event SetApp(bytes32 indexed namespace, bytes32 indexed appId, address app);
}


// This should be an interface, but interfaces can't inherit yet :(
contract IKernel is IKernelEvents, IVaultRecoverable {
    function acl() public view returns (IACL);
    function hasPermission(address who, address where, bytes32 what, bytes how) public view returns (bool);

    function setApp(bytes32 namespace, bytes32 appId, address app) public;
    function getApp(bytes32 namespace, bytes32 appId) public view returns (address);
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;


interface IACL {
    function initialize(address permissionsCreator) external;

    // TODO: this should be external
    // See https://github.com/ethereum/solidity/issues/4832
    function hasPermission(address who, address where, bytes32 what, bytes how) public view returns (bool);
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;


interface IVaultRecoverable {
    event RecoverToVault(address indexed vault, address indexed token, uint256 amount);

    function transferToVault(address token) external;

    function allowRecoverability(address token) external view returns (bool);
    function getRecoveryVault() external view returns (address);
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;

import "./Initializable.sol";


contract Petrifiable is Initializable {
    // Use block UINT256_MAX (which should be never) as the initializable date
    uint256 internal constant PETRIFIED_BLOCK = uint256(-1);

    function isPetrified() public view returns (bool) {
        return getInitializationBlock() == PETRIFIED_BLOCK;
    }

    /**
    * @dev Function to be called by top level contract to prevent being initialized.
    *      Useful for freezing base contracts when they're used behind proxies.
    */
    function petrify() internal onlyInit {
        initializedAt(PETRIFIED_BLOCK);
    }
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;

import "./TimeHelpers.sol";
import "./UnstructuredStorage.sol";


contract Initializable is TimeHelpers {
    using UnstructuredStorage for bytes32;

    // keccak256("aragonOS.initializable.initializationBlock")
    bytes32 internal constant INITIALIZATION_BLOCK_POSITION = 0xebb05b386a8d34882b8711d156f463690983dc47815980fb82aeeff1aa43579e;

    string private constant ERROR_ALREADY_INITIALIZED = "INIT_ALREADY_INITIALIZED";
    string private constant ERROR_NOT_INITIALIZED = "INIT_NOT_INITIALIZED";

    modifier onlyInit {
        require(getInitializationBlock() == 0, ERROR_ALREADY_INITIALIZED);
        _;
    }

    modifier isInitialized {
        require(hasInitialized(), ERROR_NOT_INITIALIZED);
        _;
    }

    /**
    * @return Block number in which the contract was initialized
    */
    function getInitializationBlock() public view returns (uint256) {
        return INITIALIZATION_BLOCK_POSITION.getStorageUint256();
    }

    /**
    * @return Whether the contract has been initialized by the time of the current block
    */
    function hasInitialized() public view returns (bool) {
        uint256 initializationBlock = getInitializationBlock();
        return initializationBlock != 0 && getBlockNumber() >= initializationBlock;
    }

    /**
    * @dev Function to be called by top level contract after initialization has finished.
    */
    function initialized() internal onlyInit {
        INITIALIZATION_BLOCK_POSITION.setStorageUint256(getBlockNumber());
    }

    /**
    * @dev Function to be called by top level contract after initialization to enable the contract
    *      at a future block number rather than immediately.
    */
    function initializedAt(uint256 _blockNumber) internal onlyInit {
        INITIALIZATION_BLOCK_POSITION.setStorageUint256(_blockNumber);
    }
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;

import "./Uint256Helpers.sol";


contract TimeHelpers {
    using Uint256Helpers for uint256;

    /**
    * @dev Returns the current block number.
    *      Using a function rather than `block.number` allows us to easily mock the block number in
    *      tests.
    */
    function getBlockNumber() internal view returns (uint256) {
        return block.number;
    }

    /**
    * @dev Returns the current block number, converted to uint64.
    *      Using a function rather than `block.number` allows us to easily mock the block number in
    *      tests.
    */
    function getBlockNumber64() internal view returns (uint64) {
        return getBlockNumber().toUint64();
    }

    /**
    * @dev Returns the current timestamp.
    *      Using a function rather than `block.timestamp` allows us to easily mock it in
    *      tests.
    */
    function getTimestamp() internal view returns (uint256) {
        return block.timestamp; // solium-disable-line security/no-block-members
    }

    /**
    * @dev Returns the current timestamp, converted to uint64.
    *      Using a function rather than `block.timestamp` allows us to easily mock it in
    *      tests.
    */
    function getTimestamp64() internal view returns (uint64) {
        return getTimestamp().toUint64();
    }
}

File 26 of 35 : Uint256Helpers.sol
pragma solidity ^0.4.24;


library Uint256Helpers {
    uint256 private constant MAX_UINT64 = uint64(-1);

    string private constant ERROR_NUMBER_TOO_BIG = "UINT64_NUMBER_TOO_BIG";

    function toUint64(uint256 a) internal pure returns (uint64) {
        require(a <= MAX_UINT64, ERROR_NUMBER_TOO_BIG);
        return uint64(a);
    }
}

// See https://github.com/OpenZeppelin/openzeppelin-solidity/blob/a9f910d34f0ab33a1ae5e714f69f9596a02b4d91/contracts/token/ERC20/ERC20.sol

pragma solidity ^0.4.24;


/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
contract ERC20 {
    function totalSupply() public view returns (uint256);

    function balanceOf(address _who) public view returns (uint256);

    function allowance(address _owner, address _spender)
        public view returns (uint256);

    function transfer(address _to, uint256 _value) public returns (bool);

    function approve(address _spender, uint256 _value)
        public returns (bool);

    function transferFrom(address _from, address _to, uint256 _value)
        public returns (bool);

    event Transfer(
        address indexed from,
        address indexed to,
        uint256 value
    );

    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}

File 28 of 35 : EtherTokenConstant.sol
/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;


// aragonOS and aragon-apps rely on address(0) to denote native ETH, in
// contracts where both tokens and ETH are accepted
contract EtherTokenConstant {
    address internal constant ETH = address(0);
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;


contract IsContract {
    /*
    * NOTE: this should NEVER be used for authentication
    * (see pitfalls: https://github.com/fergarrui/ethereum-security/tree/master/contracts/extcodesize).
    *
    * This is only intended to be used as a sanity check that an address is actually a contract,
    * RATHER THAN an address not being a contract.
    */
    function isContract(address _target) internal view returns (bool) {
        if (_target == address(0)) {
            return false;
        }

        uint256 size;
        assembly { size := extcodesize(_target) }
        return size > 0;
    }
}

// Inspired by AdEx (https://github.com/AdExNetwork/adex-protocol-eth/blob/b9df617829661a7518ee10f4cb6c4108659dd6d5/contracts/libs/SafeERC20.sol)
// and 0x (https://github.com/0xProject/0x-monorepo/blob/737d1dc54d72872e24abce5a1dbe1b66d35fa21a/contracts/protocol/contracts/protocol/AssetProxy/ERC20Proxy.sol#L143)

pragma solidity ^0.4.24;

import "../lib/token/ERC20.sol";


library SafeERC20 {
    // Before 0.5, solidity has a mismatch between `address.transfer()` and `token.transfer()`:
    // https://github.com/ethereum/solidity/issues/3544
    bytes4 private constant TRANSFER_SELECTOR = 0xa9059cbb;

    string private constant ERROR_TOKEN_BALANCE_REVERTED = "SAFE_ERC_20_BALANCE_REVERTED";
    string private constant ERROR_TOKEN_ALLOWANCE_REVERTED = "SAFE_ERC_20_ALLOWANCE_REVERTED";

    function invokeAndCheckSuccess(address _addr, bytes memory _calldata)
        private
        returns (bool)
    {
        bool ret;
        assembly {
            let ptr := mload(0x40)    // free memory pointer

            let success := call(
                gas,                  // forward all gas
                _addr,                // address
                0,                    // no value
                add(_calldata, 0x20), // calldata start
                mload(_calldata),     // calldata length
                ptr,                  // write output over free memory
                0x20                  // uint256 return
            )

            if gt(success, 0) {
                // Check number of bytes returned from last function call
                switch returndatasize

                // No bytes returned: assume success
                case 0 {
                    ret := 1
                }

                // 32 bytes returned: check if non-zero
                case 0x20 {
                    // Only return success if returned data was true
                    // Already have output in ptr
                    ret := eq(mload(ptr), 1)
                }

                // Not sure what was returned: don't mark as success
                default { }
            }
        }
        return ret;
    }

    function staticInvoke(address _addr, bytes memory _calldata)
        private
        view
        returns (bool, uint256)
    {
        bool success;
        uint256 ret;
        assembly {
            let ptr := mload(0x40)    // free memory pointer

            success := staticcall(
                gas,                  // forward all gas
                _addr,                // address
                add(_calldata, 0x20), // calldata start
                mload(_calldata),     // calldata length
                ptr,                  // write output over free memory
                0x20                  // uint256 return
            )

            if gt(success, 0) {
                ret := mload(ptr)
            }
        }
        return (success, ret);
    }

    /**
    * @dev Same as a standards-compliant ERC20.transfer() that never reverts (returns false).
    *      Note that this makes an external call to the token.
    */
    function safeTransfer(ERC20 _token, address _to, uint256 _amount) internal returns (bool) {
        bytes memory transferCallData = abi.encodeWithSelector(
            TRANSFER_SELECTOR,
            _to,
            _amount
        );
        return invokeAndCheckSuccess(_token, transferCallData);
    }

    /**
    * @dev Same as a standards-compliant ERC20.transferFrom() that never reverts (returns false).
    *      Note that this makes an external call to the token.
    */
    function safeTransferFrom(ERC20 _token, address _from, address _to, uint256 _amount) internal returns (bool) {
        bytes memory transferFromCallData = abi.encodeWithSelector(
            _token.transferFrom.selector,
            _from,
            _to,
            _amount
        );
        return invokeAndCheckSuccess(_token, transferFromCallData);
    }

    /**
    * @dev Same as a standards-compliant ERC20.approve() that never reverts (returns false).
    *      Note that this makes an external call to the token.
    */
    function safeApprove(ERC20 _token, address _spender, uint256 _amount) internal returns (bool) {
        bytes memory approveCallData = abi.encodeWithSelector(
            _token.approve.selector,
            _spender,
            _amount
        );
        return invokeAndCheckSuccess(_token, approveCallData);
    }

    /**
    * @dev Static call into ERC20.balanceOf().
    * Reverts if the call fails for some reason (should never fail).
    */
    function staticBalanceOf(ERC20 _token, address _owner) internal view returns (uint256) {
        bytes memory balanceOfCallData = abi.encodeWithSelector(
            _token.balanceOf.selector,
            _owner
        );

        (bool success, uint256 tokenBalance) = staticInvoke(_token, balanceOfCallData);
        require(success, ERROR_TOKEN_BALANCE_REVERTED);

        return tokenBalance;
    }

    /**
    * @dev Static call into ERC20.allowance().
    * Reverts if the call fails for some reason (should never fail).
    */
    function staticAllowance(ERC20 _token, address _owner, address _spender) internal view returns (uint256) {
        bytes memory allowanceCallData = abi.encodeWithSelector(
            _token.allowance.selector,
            _owner,
            _spender
        );

        (bool success, uint256 allowance) = staticInvoke(_token, allowanceCallData);
        require(success, ERROR_TOKEN_ALLOWANCE_REVERTED);

        return allowance;
    }

    /**
    * @dev Static call into ERC20.totalSupply().
    * Reverts if the call fails for some reason (should never fail).
    */
    function staticTotalSupply(ERC20 _token) internal view returns (uint256) {
        bytes memory totalSupplyCallData = abi.encodeWithSelector(_token.totalSupply.selector);

        (bool success, uint256 totalSupply) = staticInvoke(_token, totalSupplyCallData);
        require(success, ERROR_TOKEN_ALLOWANCE_REVERTED);

        return totalSupply;
    }
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;


interface IEVMScriptExecutor {
    function execScript(bytes script, bytes input, address[] blacklist) external returns (bytes);
    function executorType() external pure returns (bytes32);
}

/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;

import "./IEVMScriptExecutor.sol";


contract EVMScriptRegistryConstants {
    /* Hardcoded constants to save gas
    bytes32 internal constant EVMSCRIPT_REGISTRY_APP_ID = apmNamehash("evmreg");
    */
    bytes32 internal constant EVMSCRIPT_REGISTRY_APP_ID = 0xddbcfd564f642ab5627cf68b9b7d374fb4f8a36e941a75d89c87998cef03bd61;
}


interface IEVMScriptRegistry {
    function addScriptExecutor(IEVMScriptExecutor executor) external returns (uint id);
    function disableScriptExecutor(uint256 executorId) external;

    // TODO: this should be external
    // See https://github.com/ethereum/solidity/issues/4832
    function getScriptExecutor(bytes script) public view returns (IEVMScriptExecutor);
}

File 33 of 35 : KernelConstants.sol
/*
 * SPDX-License-Identifier:    MIT
 */

pragma solidity ^0.4.24;


contract KernelAppIds {
    /* Hardcoded constants to save gas
    bytes32 internal constant KERNEL_CORE_APP_ID = apmNamehash("kernel");
    bytes32 internal constant KERNEL_DEFAULT_ACL_APP_ID = apmNamehash("acl");
    bytes32 internal constant KERNEL_DEFAULT_VAULT_APP_ID = apmNamehash("vault");
    */
    bytes32 internal constant KERNEL_CORE_APP_ID = 0x3b4bf6bf3ad5000ecf0f989d5befde585c6860fea3e574a4fab4c49d1c177d9c;
    bytes32 internal constant KERNEL_DEFAULT_ACL_APP_ID = 0xe3262375f45a6e2026b7e7b18c2b807434f2508fe1a2a3dfb493c7df8f4aad6a;
    bytes32 internal constant KERNEL_DEFAULT_VAULT_APP_ID = 0x7e852e0fcfce6551c13800f1e7476f982525c2b5277ba14b24339c68416336d1;
}


contract KernelNamespaceConstants {
    /* Hardcoded constants to save gas
    bytes32 internal constant KERNEL_CORE_NAMESPACE = keccak256("core");
    bytes32 internal constant KERNEL_APP_BASES_NAMESPACE = keccak256("base");
    bytes32 internal constant KERNEL_APP_ADDR_NAMESPACE = keccak256("app");
    */
    bytes32 internal constant KERNEL_CORE_NAMESPACE = 0xc681a85306374a5ab27f0bbc385296a54bcd314a1948b6cf61c4ea1bc44bb9f8;
    bytes32 internal constant KERNEL_APP_BASES_NAMESPACE = 0xf1f3eb40f5bc1ad1344716ced8b8a0431d840b5783aea1fd01786bc26f35ac0f;
    bytes32 internal constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
}

pragma solidity ^0.4.24;

/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
interface IERC20 {
  function totalSupply() external view returns (uint256);

  function balanceOf(address who) external view returns (uint256);

  function allowance(address owner, address spender)
    external view returns (uint256);

  function transfer(address to, uint256 value) external returns (bool);

  function approve(address spender, uint256 value)
    external returns (bool);

  function transferFrom(address from, address to, uint256 value)
    external returns (bool);

  event Transfer(
    address indexed from,
    address indexed to,
    uint256 value
  );

  event Approval(
    address indexed owner,
    address indexed spender,
    uint256 value
  );
}

// SPDX-FileCopyrightText: 2020 Lido <[email protected]>

// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.4.24;

import "@aragon/os/contracts/common/UnstructuredStorage.sol";


contract Pausable {
    using UnstructuredStorage for bytes32;

    event Stopped();
    event Resumed();

    bytes32 internal constant ACTIVE_FLAG_POSITION = keccak256("lido.Pausable.activeFlag");

    modifier whenNotStopped() {
        require(ACTIVE_FLAG_POSITION.getStorageBool(), "CONTRACT_IS_STOPPED");
        _;
    }

    modifier whenStopped() {
        require(!ACTIVE_FLAG_POSITION.getStorageBool(), "CONTRACT_IS_ACTIVE");
        _;
    }

    function isStopped() external view returns (bool) {
        return !ACTIVE_FLAG_POSITION.getStorageBool();
    }

    function _stop() internal whenNotStopped {
        ACTIVE_FLAG_POSITION.setStorageBool(false);
        emit Stopped();
    }

    function _resume() internal whenStopped {
        ACTIVE_FLAG_POSITION.setStorageBool(true);
        emit Resumed();
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "evmVersion": "constantinople",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"constant":false,"inputs":[],"name":"resume","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_CONTROL_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_depositContract","type":"address"},{"name":"_oracle","type":"address"},{"name":"_operators","type":"address"},{"name":"_treasury","type":"address"},{"name":"_insuranceFund","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getInsuranceFund","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_ethAmount","type":"uint256"}],"name":"getSharesByPooledEth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStakingPaused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getOperators","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxStakeLimit","type":"uint256"},{"name":"_stakeLimitIncreasePerBlock","type":"uint256"}],"name":"setStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"RESUME_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DEPOSIT_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DEPOSIT_SIZE","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalPooledEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTreasury","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStopped","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_WITHDRAWAL_KEY","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBufferedEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"receiveELRewards","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getELRewardsWithdrawalLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SIGNATURE_LENGTH","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getWithdrawalCredentials","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentStakeLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_limitPoints","type":"uint16"}],"name":"setELRewardsWithdrawalLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_beaconValidators","type":"uint256"},{"name":"_beaconBalance","type":"uint256"}],"name":"handleOracleReport","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getStakeLimitFullInfo","outputs":[{"name":"isStakingPaused","type":"bool"},{"name":"isStakingLimitSet","type":"bool"},{"name":"currentStakeLimit","type":"uint256"},{"name":"maxStakeLimit","type":"uint256"},{"name":"maxStakeLimitGrowthBlocks","type":"uint256"},{"name":"prevStakeLimit","type":"uint256"},{"name":"prevStakeBlockNumber","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SET_EL_REWARDS_WITHDRAWAL_LIMIT_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getELRewardsVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"resumeStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getFeeDistribution","outputs":[{"name":"treasuryFeeBasisPoints","type":"uint16"},{"name":"insuranceFeeBasisPoints","type":"uint16"},{"name":"operatorsFeeBasisPoints","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_sharesAmount","type":"uint256"}],"name":"getPooledEthByShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_executionLayerRewardsVault","type":"address"}],"name":"setELRewardsVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_PROTOCOL_CONTRACTS_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getOracle","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_treasuryFeeBasisPoints","type":"uint16"},{"name":"_insuranceFeeBasisPoints","type":"uint16"},{"name":"_operatorsFeeBasisPoints","type":"uint16"}],"name":"setFeeDistribution","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_feeBasisPoints","type":"uint16"}],"name":"setFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_maxDeposits","type":"uint256"}],"name":"depositBufferedEther","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_FEE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_referral","type":"address"}],"name":"submit","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"WITHDRAWAL_CREDENTIALS_LENGTH","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PUBKEY_LENGTH","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SET_EL_REWARDS_VAULT_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getDepositContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBeaconStat","outputs":[{"name":"depositedValidators","type":"uint256"},{"name":"beaconValidators","type":"uint256"},{"name":"beaconBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"removeStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"BURN_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getFee","outputs":[{"name":"feeBasisPoints","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_oracle","type":"address"},{"name":"_treasury","type":"address"},{"name":"_insuranceFund","type":"address"}],"name":"setProtocolContracts","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_withdrawalCredentials","type":"bytes32"}],"name":"setWithdrawalCredentials","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"depositBufferedEther","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_account","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"burnShares","outputs":[{"name":"newTotalShares","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"sharesOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pauseStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTotalELRewardsCollected","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"sharesValue","type":"uint256"}],"name":"TransferShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"},{"indexed":false,"name":"preRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"postRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"sharesAmount","type":"uint256"}],"name":"SharesBurnt","type":"event"},{"anonymous":false,"inputs":[],"name":"Stopped","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingResumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"maxStakeLimit","type":"uint256"},{"indexed":false,"name":"stakeLimitIncreasePerBlock","type":"uint256"}],"name":"StakingLimitSet","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingLimitRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"oracle","type":"address"},{"indexed":false,"name":"treasury","type":"address"},{"indexed":false,"name":"insuranceFund","type":"address"}],"name":"ProtocolContactsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"feeBasisPoints","type":"uint16"}],"name":"FeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"treasuryFeeBasisPoints","type":"uint16"},{"indexed":false,"name":"insuranceFeeBasisPoints","type":"uint16"},{"indexed":false,"name":"operatorsFeeBasisPoints","type":"uint16"}],"name":"FeeDistributionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"ELRewardsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"limitPoints","type":"uint256"}],"name":"ELRewardsWithdrawalLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"withdrawalCredentials","type":"bytes32"}],"name":"WithdrawalCredentialsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"executionLayerRewardsVault","type":"address"}],"name":"ELRewardsVaultSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"referral","type":"address"}],"name":"Submitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Unbuffered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"tokenAmount","type":"uint256"},{"indexed":false,"name":"sentFromBuffer","type":"uint256"},{"indexed":true,"name":"pubkeyHash","type":"bytes32"},{"indexed":false,"name":"etherAmount","type":"uint256"}],"name":"Withdrawal","type":"event"}]

6080604052620000146200001a60201b60201c565b62000231565b6200002a6200011c60201b60201c565b60408051808201909152601881527f494e49545f414c52454144595f494e495449414c495a454400000000000000006020820152901562000106576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620000ca578181015183820152602001620000b0565b50505050905090810190601f168015620000f85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506200011a6000196200014f60201b60201c565b565b60006200014a6000805160206200616283398151915260001b600019166200022960201b62003e6f1760201c565b905090565b6200015f6200011c60201b60201c565b60408051808201909152601881527f494e49545f414c52454144595f494e495449414c495a4544000000000000000060208201529015620001fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252838181518152602001915080519060200190808383600083811015620000ca578181015183820152602001620000b0565b506200022660008051602062006162833981519152826200022d602090811b6200362617901c565b50565b5490565b9055565b615f2180620002416000396000f30060806040526004361061037e5760003560e01c63ffffffff168063046f7da2146103e157806306fdde03146103f857806307da68f5146104825780630803fac014610497578063095ea7b3146104c0578063136dd43c146104e45780631459457a1461050b578063158626f71461054457806318160ddd14610575578063192084511461058a5780631ea7ca89146105a257806323b872dd146105b757806327a099d8146105e15780632914b9bd146105f65780632cb5f7841461064f5780632de03aa11461066a578063313ce5671461067f57806332f0a3b5146106aa578063353efdcf146106bf57806336bf3325146106d457806337cfdaca14610575578063389ed267146106e957806339509351146106fe5780633b19e84a146107225780633f683b6a14610737578063435721da1461074c57806347b714e0146107615780634ad509b21461077657806352b3af931461077e578063540bc5ea1461079357806356396715146107a8578063609c4c6c146107bd57806363c2eb53146107d257806364f9991a146107ee578063665b4b0b146108095780636bb98ad314610858578063706aa30d1461086d57806370a08231146108825780637475f913146108a3578063752f77f1146108b85780637a28fb88146108f35780637e4193c61461090b5780637e7db6e11461092c5780637f6fdac71461094d57806380afdea814610962578063833b1fce146109775780638b3dd7491461098c5780638cef3612146109a15780638e005553146109c95780638fcb4e5b146109e557806390adc83b14610a0957806395d89b4114610a215780639aaa2d1514610a365780639d4941d814610a4b578063a1658fad14610a6c578063a1903eab14610ad3578063a30448c014610ae7578063a457c2d714610afc578063a479e50814610b20578063a4d55d1d14610b35578063a6426f5f14610b4a578063a9059cbb14610b5f578063ab94276a14610b83578063ae2e353814610b98578063b3320d9a14610bcb578063b930908f14610be0578063ced72f8714610bf5578063d4aae0c414610c21578063d5002f2e14610c36578063dd62ed3e14610c4b578063de4796ed14610c72578063e73f452914610c87578063e97ee8cc14610cb4578063eb85262f14610ccc578063ecc1dcfb14610ce1578063ee7a7c0414610cf6578063f5eb42dc14610d1a578063f999c50614610d3b578063fa64ebac14610d50575b36156103d4576040805160e560020a62461bcd02815260206004820152600e60248201527f4e4f4e5f454d5054595f44415441000000000000000000000000000000000000604482015290519081900360640190fd5b6103de6000610d65565b50005b3480156103ed57600080fd5b506103f6610fd5565b005b34801561040457600080fd5b5061040d611022565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561044757818101518382015260200161042f565b50505050905090810190601f1680156104745780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561048e57600080fd5b506103f6611059565b3480156104a357600080fd5b506104ac6110a4565b604080519115158252519081900360200190f35b3480156104cc57600080fd5b506104ac600160a060020a03600435166024356110cd565b3480156104f057600080fd5b506104f96110e3565b60408051918252519081900360200190f35b34801561051757600080fd5b506103f6600160a060020a0360043581169060243581169060443581169060643581169060843516611106565b34801561055057600080fd5b5061055961126e565b60408051600160a060020a039092168252519081900360200190f35b34801561058157600080fd5b506104f96112b1565b34801561059657600080fd5b506104f96004356112bb565b3480156105ae57600080fd5b506104ac611309565b3480156105c357600080fd5b506104ac600160a060020a036004358116906024351660443561133e565b3480156105ed57600080fd5b50610559611412565b34801561060257600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526105599436949293602493928401919081908401838280828437509497506114509650505050505050565b34801561065b57600080fd5b506103f6600435602435611535565b34801561067657600080fd5b506104f96115df565b34801561068b57600080fd5b50610694611614565b6040805160ff9092168252519081900360200190f35b3480156106b657600080fd5b50610559611619565b3480156106cb57600080fd5b506104f961168e565b3480156106e057600080fd5b506104f96116c3565b3480156106f557600080fd5b506104f96116d0565b34801561070a57600080fd5b506104ac600160a060020a0360043516602435611705565b34801561072e57600080fd5b50610559611741565b34801561074357600080fd5b506104ac61177f565b34801561075857600080fd5b506104f96117b1565b34801561076d57600080fd5b506104f96117e6565b6103f66117f0565b34801561078a57600080fd5b506104f9611969565b34801561079f57600080fd5b506104f96119cd565b3480156107b457600080fd5b506104f96119d2565b3480156107c957600080fd5b506104f9611a10565b3480156107de57600080fd5b506103f661ffff60043516611a45565b3480156107fa57600080fd5b506103f6600435602435611b42565b34801561081557600080fd5b5061081e611f42565b6040805197151588529515156020880152868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b34801561086457600080fd5b506104f9611fe5565b34801561087957600080fd5b50610559612040565b34801561088e57600080fd5b506104f9600160a060020a03600435166120a4565b3480156108af57600080fd5b506103f66120bd565b3480156108c457600080fd5b506108cd6120e6565b6040805161ffff9485168152928416602084015292168183015290519081900360600190f35b3480156108ff57600080fd5b506104f96004356121ab565b34801561091757600080fd5b506103f6600160a060020a03600435166121d7565b34801561093857600080fd5b506104ac600160a060020a03600435166122b9565b34801561095957600080fd5b506104f96122bf565b34801561096e57600080fd5b506104f96122f4565b34801561098357600080fd5b5061055961231f565b34801561099857600080fd5b506104f961235d565b3480156109ad57600080fd5b506103f661ffff60043581169060243581169060443516612388565b3480156109d557600080fd5b506103f661ffff6004351661253d565b3480156109f157600080fd5b506104f9600160a060020a03600435166024356125ee565b348015610a1557600080fd5b506103f6600435612694565b348015610a2d57600080fd5b5061040d6126db565b348015610a4257600080fd5b506104f9612712565b348015610a5757600080fd5b506103f6600160a060020a0360043516612747565b348015610a7857600080fd5b5060408051602060046044358181013583810280860185019096528085526104ac958335600160a060020a03169560248035963696956064959394920192918291850190849080828437509497506129879650505050505050565b6104f9600160a060020a0360043516612ad2565b348015610af357600080fd5b506104f9612add565b348015610b0857600080fd5b506104ac600160a060020a0360043516602435612ae2565b348015610b2c57600080fd5b50610559612b7d565b348015610b4157600080fd5b506104f9612c64565b348015610b5657600080fd5b506104f9612c69565b348015610b6b57600080fd5b506104ac600160a060020a0360043516602435612c9e565b348015610b8f57600080fd5b50610559612cab565b348015610ba457600080fd5b50610bad612ce9565b60408051938452602084019290925282820152519081900360600190f35b348015610bd757600080fd5b506103f6612d71565b348015610bec57600080fd5b506104f9612dfb565b348015610c0157600080fd5b50610c0a612e30565b6040805161ffff9092168252519081900360200190f35b348015610c2d57600080fd5b50610559612e6e565b348015610c4257600080fd5b506104f9612e99565b348015610c5757600080fd5b506104f9600160a060020a0360043581169060243516612ea3565b348015610c7e57600080fd5b506104ac612ece565b348015610c9357600080fd5b506103f6600160a060020a0360043581169060243581169060443516612ee1565b348015610cc057600080fd5b506103f6600435612f2c565b348015610cd857600080fd5b506104f961303a565b348015610ced57600080fd5b506103f661306f565b348015610d0257600080fd5b506104f9600160a060020a03600435166024356130b4565b348015610d2657600080fd5b506104f9600160a060020a0360043516613198565b348015610d4757600080fd5b506103f66131a3565b348015610d5c57600080fd5b506104f96131de565b6000610d6f615dee565b600080341515610dc9576040805160e560020a62461bcd02815260206004820152600c60248201527f5a45524f5f4445504f5349540000000000000000000000000000000000000000604482015290519081900360640190fd5b60408051600080516020615e1683398151915281529051908190036014019020610df290613242565b9250610dfd83613295565b15610e52576040805160e560020a62461bcd02815260206004820152600e60248201527f5354414b494e475f504155534544000000000000000000000000000000000000604482015290519081900360640190fd5b610e5b836132a0565b15610f0457610e69836132b2565b915034821015610ec3576040805160e560020a62461bcd02815260206004820152600b60248201527f5354414b455f4c494d4954000000000000000000000000000000000000000000604482015290519081900360640190fd5b610f04610ed88434850363ffffffff61333d16565b60408051600080516020615e16833981519152815290519081900360140190209063ffffffff61338116565b610f0d346112bb565b9050801515610f195750345b610f2333826133e0565b50610f7d610f3f34610f3361354b565b9063ffffffff61359816565b604080517f6c69646f2e4c69646f2e62756666657265644574686572000000000000000000815290519081900360170190209063ffffffff61362616565b60408051348152600160a060020a0387166020820152815133927f96a25c8ce0baabc1fdefd93e9ed25d8e092a3332f3aa9a41722b5697231d1d1a928290030190a2610fc9338261362a565b8093505b505050919050565b604080517f524553554d455f524f4c450000000000000000000000000000000000000000008152905190819003600b019020611010906136b6565b611018613773565b61102061384d565b565b60408051808201909152601781527f4c6971756964207374616b656420457468657220322e30000000000000000000602082015290565b604080517f50415553455f524f4c45000000000000000000000000000000000000000000008152905190819003600a019020611094906136b6565b61109c6138b8565b611020613981565b6000806110af61235d565b905080158015906110c75750806110c46139e0565b10155b91505090565b60006110da3384846139e4565b50600192915050565b60408051600080516020615eb68339815191528152905190819003601401902081565b61110e61235d565b60408051808201909152601881527f494e49545f414c52454144595f494e495449414c495a45440000000000000000602082015290156111cf5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561119457818101518382015260200161117c565b50505050905090810190601f1680156111c15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50604080517f6c69646f2e4c69646f2e6e6f64654f70657261746f72735265676973747279008152905190819003601f019020611212908463ffffffff61362616565b604080517f6c69646f2e4c69646f2e6465706f736974436f6e74726163740000000000000081529051908190036019019020611254908663ffffffff61362616565b61125f848383613b73565b611267613da9565b5050505050565b604080517f6c69646f2e4c69646f2e696e737572616e636546756e64000000000000000000815290519081900360170190206000906112ac90613e6f565b905090565b60006112ac613e73565b6000806112c6613e73565b90508015156112d85760009150611303565b611300816112f46112e7613eb5565b869063ffffffff613ef316565b9063ffffffff613f9e16565b91505b50919050565b60408051600080516020615e16833981519152815290519081900360140190206000906112ac9061133990613242565b613295565b600160a060020a0383166000908152600160209081526040808320338452909152812054828110156113e0576040805160e560020a62461bcd02815260206004820152602160248201527f5452414e534645525f414d4f554e545f455843454544535f414c4c4f57414e4360448201527f4500000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b6113eb85858561403e565b6114058533611400848763ffffffff6140f216565b6139e4565b600191505b509392505050565b604080517f6c69646f2e4c69646f2e6e6f64654f70657261746f72735265676973747279008152905190819003601f0190206000906112ac90613e6f565b600061145a612b7d565b600160a060020a03166304bf2a7f836040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156114b557818101518382015260200161149d565b50505050905090810190601f1680156114e25780820380516001836020036101000a031916815260200191505b5092505050602060405180830381600087803b15801561150157600080fd5b505af1158015611515573d6000803e3d6000fd5b505050506040513d602081101561152b57600080fd5b505190505b919050565b60408051600080516020615eb68339815191528152905190819003601401902061155e906136b6565b60408051600080516020615e16833981519152815290519081900360140190206115a090610ed8908490849061159390613242565b919063ffffffff61418616565b604080518381526020810183905281517fce9fddf6179affa1ea7bf36d80a6bf0284e0f3b91f4b2fa6eea2af923e7fac2d929181900390910190a15050565b604080517f524553554d455f524f4c450000000000000000000000000000000000000000008152905190819003600b01902081565b601290565b6000611623612e6e565b600160a060020a03166332f0a3b56040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561165d57600080fd5b505af1158015611671573d6000803e3d6000fd5b505050506040513d602081101561168757600080fd5b5051905090565b604080517f4445504f5349545f524f4c4500000000000000000000000000000000000000008152905190819003600c01902081565b6801bc16d674ec80000081565b604080517f50415553455f524f4c45000000000000000000000000000000000000000000008152905190819003600a01902081565b336000818152600160209081526040808320600160a060020a038716845290915281205490916110da918590611400908663ffffffff61359816565b604080517f6c69646f2e4c69646f2e74726561737572790000000000000000000000000000815290519081900360120190206000906112ac90613e6f565b60408051600080516020615e56833981519152815290519081900360180190206000906117ab90613e6f565b15905090565b604080517f4d414e4147455f5749544844524157414c5f4b455900000000000000000000008152905190819003601501902081565b60006112ac61354b565b604080517f6c69646f2e4c69646f2e657865637574696f6e4c61796572526577617264735681527f61756c74000000000000000000000000000000000000000000000000000000006020820152905190819003602401902061185190613e6f565b600160a060020a0316331461186557600080fd5b604080517f6c69646f2e4c69646f2e746f74616c454c52657761726473436f6c6c6563746581527f640000000000000000000000000000000000000000000000000000000000000060208201529051908190036021019020611934906118d0903490610f3390613e6f565b604080517f6c69646f2e4c69646f2e746f74616c454c52657761726473436f6c6c6563746581527f6400000000000000000000000000000000000000000000000000000000000000602082015290519081900360210190209063ffffffff61362616565b6040805134815290517fd27f9b0c98bdee27044afa149eadcd2047d6399cb6613a45c5b87e6aca76e6b59181900360200190a1565b604080517f6c69646f2e4c69646f2e454c526577617264735769746864726177616c4c696d81527f6974000000000000000000000000000000000000000000000000000000000000602082015290519081900360220190206000906112ac90613e6f565b606081565b604080517f6c69646f2e4c69646f2e7769746864726177616c43726564656e7469616c73008152905190819003601f0190206000906112ac90613e6f565b60408051600080516020615e16833981519152815290519081900360140190206000906112ac90611a4090613242565b61439e565b604080517f5345545f454c5f524557415244535f5749544844524157414c5f4c494d49545f81527f524f4c450000000000000000000000000000000000000000000000000000000060208201529051908190036024019020611aa6906136b6565b604080517f6c69646f2e4c69646f2e454c526577617264735769746864726177616c4c696d81527f697400000000000000000000000000000000000000000000000000000000000060208201529051908190036022019020611b0890826143d7565b6040805161ffff8316815290517f166eb213129ab51688433b859b5a206403ee174774a1430f8ffb83af316161f69181900360200190a150565b6000806000806000806000611b7d6040518080600080516020615e568339815191528152506018019050604051809103902060001916613e6f565b1515611bc1576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b611bc961231f565b600160a060020a03163314611c28576040805160e560020a62461bcd02815260206004820152600f60248201527f4150505f415554485f4641494c45440000000000000000000000000000000000604482015290519081900360640190fd5b60408051600080516020615e768339815191528152905190819003601d019020611c5190613e6f565b965086891115611cab576040805160e560020a62461bcd02815260206004820152601760248201527f5245504f525445445f4d4f52455f4445504f5349544544000000000000000000604482015290519081900360640190fd5b60408051600080516020615ed68339815191528152905190819003601a019020611cd490613e6f565b955085891015611d2e576040805160e560020a62461bcd02815260206004820152601860248201527f5245504f525445445f4c4553535f56414c494441544f52530000000000000000604482015290519081900360640190fd5b611d3e898763ffffffff6140f216565b60408051600080516020615e3683398151915281529051908190036017019020909550611d8790611d6e90613e6f565b610f33876801bc16d674ec80000063ffffffff613ef316565b60408051600080516020615e3683398151915281529051908190036017019020909450611dba908963ffffffff61362616565b60408051600080516020615ed68339815191528152905190819003601a019020611dea908a63ffffffff61362616565b611df2612040565b9150600160a060020a03821615611f0557604080517f6c69646f2e4c69646f2e454c526577617264735769746864726177616c4c696d81527f697400000000000000000000000000000000000000000000000000000000000060208201529051908190036022019020600160a060020a03831690639342c8f49061271090611e7990613e6f565b611e81613e73565b02811515611e8b57fe5b046040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015611ec257600080fd5b505af1158015611ed6573d6000803e3d6000fd5b505050506040513d6020811015611eec57600080fd5b505192508215611f0557611f05610f3f84610f3361354b565b83881115611f3757611f1d888563ffffffff6140f216565b9050611f37611f32828563ffffffff61359816565b614449565b505050505050505050565b6000806000806000806000611f55615dee565b60408051600080516020615e1683398151915281529051908190036014019020611f7e90613242565b9050611f8981613295565b9750611f94816132a0565b9650611f9f8161439e565b955080606001516001606060020a03169450806040015163ffffffff16935080602001516001606060020a03169250806000015163ffffffff1691505090919293949596565b604080517f5345545f454c5f524557415244535f5749544844524157414c5f4c494d49545f81527f524f4c45000000000000000000000000000000000000000000000000000000006020820152905190819003602401902081565b604080517f6c69646f2e4c69646f2e657865637574696f6e4c61796572526577617264735681527f61756c7400000000000000000000000000000000000000000000000000000000602082015290519081900360240190206000906112ac90613e6f565b60006120b76120b283614578565b6121ab565b92915050565b60408051600080516020615eb683398151915281529051908190036014019020611018906136b6565b604080517f6c69646f2e4c69646f2e74726561737572794665650000000000000000000000815290519081900360150190206000908190819061212890613e6f565b604080517f6c69646f2e4c69646f2e696e737572616e6365466565000000000000000000008152905190819003601601902090935061216690613e6f565b604080517f6c69646f2e4c69646f2e6e6f64654f70657261746f72734665650000000000008152905190819003601a0190209092506121a490613e6f565b9050909192565b6000806121b6613eb5565b90508015156121c85760009150611303565b611300816112f46112e7613e73565b604080517f5345545f454c5f524557415244535f5641554c545f524f4c450000000000000081529051908190036019019020612212906136b6565b604080517f6c69646f2e4c69646f2e657865637574696f6e4c61796572526577617264735681527f61756c74000000000000000000000000000000000000000000000000000000006020820152905190819003602401902061227a908263ffffffff61362616565b60408051600160a060020a038316815290517f8e2d01c4cfaa88fa4d772d37e4d068deda4342bf4ef6dc4b0cf3e868be5ebb409181900360200190a150565b50600190565b604080517f4d414e4147455f50524f544f434f4c5f434f4e5452414354535f524f4c4500008152905190819003601e01902081565b60006112ac7fd625496217aa6a3453eecb9c3489dc5a53e6c67b444329ea2b2cbc9ff547639b613e6f565b604080517f6c69646f2e4c69646f2e6f7261636c6500000000000000000000000000000000815290519081900360100190206000906112ac90613e6f565b60006112ac7febb05b386a8d34882b8711d156f463690983dc47815980fb82aeeff1aa43579e613e6f565b604080517f4d414e4147455f464545000000000000000000000000000000000000000000008152905190819003600a0190206123c3906136b6565b6123e68161ffff16610f338461ffff168661ffff1661359890919063ffffffff16565b6127101461243e576040805160e560020a62461bcd02815260206004820152601060248201527f464545535f444f4e545f4144445f555000000000000000000000000000000000604482015290519081900360640190fd5b604080517f6c69646f2e4c69646f2e747265617375727946656500000000000000000000008152905190819003601501902061247a90846143d7565b604080517f6c69646f2e4c69646f2e696e737572616e636546656500000000000000000000815290519081900360160190206124b690836143d7565b604080517f6c69646f2e4c69646f2e6e6f64654f70657261746f72734665650000000000008152905190819003601a0190206124f290826143d7565b6040805161ffff8086168252808516602083015283168183015290517f034529db1bba3830b8877e116871f19c5b96ef86c739f2a05668c860c84668989181900360600190a1505050565b604080517f4d414e4147455f464545000000000000000000000000000000000000000000008152905190819003600a019020612578906136b6565b604080517f6c69646f2e4c69646f2e666565000000000000000000000000000000000000008152905190819003600d0190206125b490826143d7565b6040805161ffff8316815290517faab062e3faf62b6c9a0f8e62af66e0310e27127a8c871a67be7dd4d93de6da539181900360200190a150565b6000806125fc338585614593565b604080518481529051600160a060020a0386169133917f9d9c909296d9c674451c0c24f02cb64981eb3b727f99865939192f880a755dcb9181900360200190a3612645836121ab565b604080518281529051919250600160a060020a0386169133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef919081900360200190a38091505b5092915050565b604080517f4445504f5349545f524f4c4500000000000000000000000000000000000000008152905190819003600c0190206126cf906136b6565b6126d88161479c565b50565b60408051808201909152600581527f7374455448000000000000000000000000000000000000000000000000000000602082015290565b604080517f4d414e4147455f464545000000000000000000000000000000000000000000008152905190819003600a01902081565b6000806000612755846122b9565b15156127ab576040805160e560020a62461bcd02815260206004820152601260248201527f5245434f5645525f444953414c4c4f5745440000000000000000000000000000604482015290519081900360640190fd5b6127b3611619565b9250600160a060020a0383161515612815576040805160e560020a62461bcd02815260206004820152601260248201527f5245434f5645525f5641554c545f5a45524f0000000000000000000000000000604482015290519081900360640190fd5b600160a060020a03841615156128a95761282d614884565b915082600160a060020a03168260405160006040518083038185875af19250505015156128a4576040805160e560020a62461bcd02815260206004820152601760248201527f5245434f5645525f5452414e534645525f4641494c4544000000000000000000604482015290519081900360640190fd5b612936565b50826128c4600160a060020a0382163063ffffffff61489f16565b91506128e0600160a060020a038216848463ffffffff6149b416565b1515612936576040805160e560020a62461bcd02815260206004820152601d60248201527f5245434f5645525f544f4b454e5f5452414e534645525f4641494c4544000000604482015290519081900360640190fd5b83600160a060020a031683600160a060020a03167f596caf56044b55fb8c4ca640089bbc2b63cae3e978b851f5745cbb7c5b288e02846040518082815260200191505060405180910390a350505050565b6000806129926110a4565b15156129a1576000915061140a565b6129a9612e6e565b9050600160a060020a03811615156129c4576000915061140a565b80600160a060020a031663fdef91068630876129df88614a36565b60405163ffffffff861660e01b8152600160a060020a03808616600483019081529085166024830152604482018490526080606483019081528351608484015283519192909160a490910190602085019080838360005b83811015612a4e578181015183820152602001612a36565b50505050905090810190601f168015612a7b5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015612a9d57600080fd5b505af1158015612ab1573d6000803e3d6000fd5b505050506040513d6020811015612ac757600080fd5b505195945050505050565b60006120b782610d65565b602081565b336000908152600160209081526040808320600160a060020a038616845290915281205482811015612b5e576040805160e560020a62461bcd02815260206004820152601e60248201527f4445435245415345445f414c4c4f57414e43455f42454c4f575f5a45524f0000604482015290519081900360640190fd5b612b733385611400848763ffffffff6140f216565b5060019392505050565b600080612b88612e6e565b604080517fbe00bbd80000000000000000000000000000000000000000000000000000000081527fd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb60048201527fddbcfd564f642ab5627cf68b9b7d374fb4f8a36e941a75d89c87998cef03bd6160248201529051600160a060020a03929092169163be00bbd8916044808201926020929091908290030181600087803b158015612c3257600080fd5b505af1158015612c46573d6000803e3d6000fd5b505050506040513d6020811015612c5c57600080fd5b505192915050565b603081565b604080517f5345545f454c5f524557415244535f5641554c545f524f4c45000000000000008152905190819003601901902081565b60006110da33848461403e565b604080517f6c69646f2e4c69646f2e6465706f736974436f6e747261637400000000000000815290519081900360190190206000906112ac90613e6f565b60408051600080516020615e768339815191528152905190819003601d01902060009081908190612d1990613e6f565b60408051600080516020615ed68339815191528152905190819003601a019020909350612d4590613e6f565b60408051600080516020615e36833981519152815290519081900360170190209092506121a490613e6f565b60408051600080516020615eb683398151915281529051908190036014019020612d9a906136b6565b60408051600080516020615e1683398151915281529051908190036014019020612dd090610ed890612dcb90613242565b614a40565b6040517f9b2a687c198898fcc32a33bbc610d478f177a73ab7352023e6cc1de5bf12a3df90600090a1565b604080517f4255524e5f524f4c4500000000000000000000000000000000000000000000008152905190819003600901902081565b604080517f6c69646f2e4c69646f2e666565000000000000000000000000000000000000008152905190819003600d0190206000906112ac90613e6f565b60006112ac7f4172f0f7d2289153072b0a6ca36959e0cbe2efc3afe50fc81636caa96338137b613e6f565b60006112ac613eb5565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b6000600019612edb61235d565b14905090565b604080517f4d414e4147455f50524f544f434f4c5f434f4e5452414354535f524f4c4500008152905190819003601e019020612f1c906136b6565b612f27838383613b73565b505050565b604080517f4d414e4147455f5749544844524157414c5f4b4559000000000000000000000081529051908190036015019020612f67906136b6565b604080517f6c69646f2e4c69646f2e7769746864726177616c43726564656e7469616c73008152905190819003601f019020612fa9908263ffffffff61362616565b612fb1611412565b600160a060020a031663f778021e6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612feb57600080fd5b505af1158015612fff573d6000803e3d6000fd5b50506040805184815290517f13eb80e900aa05a2696d50d5de33ef631c73493c4921da233b17335ff6b7b1149350908190036020019150a150565b604080517f5354414b494e475f50415553455f524f4c4500000000000000000000000000008152905190819003601201902081565b604080517f4445504f5349545f524f4c4500000000000000000000000000000000000000008152905190819003600c0190206130aa906136b6565b611020609661479c565b604080517f4255524e5f524f4c450000000000000000000000000000000000000000000000815290519081900360090190206000906130f38484614a53565b6130fe338383612987565b60408051808201909152600f81527f4150505f415554485f4641494c4544000000000000000000000000000000000060208201529015156131845760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b5061318f8585614a6f565b95945050505050565b60006120b782614578565b604080517f5354414b494e475f50415553455f524f4c4500000000000000000000000000008152905190819003601201902061109c906136b6565b604080517f6c69646f2e4c69646f2e746f74616c454c52657761726473436f6c6c6563746581527f6400000000000000000000000000000000000000000000000000000000000000602082015290519081900360210190206000906112ac90613e6f565b61324a615dee565b600061325583613e6f565b63ffffffff600082901c811684526001606060020a03602083811c821690860152608083901c909116604085015260a09190911c16606083015250919050565b5163ffffffff161590565b606001516001606060020a0316151590565b6040810151600090819063ffffffff16156132f657826040015163ffffffff1683606001516001606060020a03168115156132e957fe5b046001606060020a031690505b80836000015163ffffffff1643030283602001516001606060020a031601915082606001516001606060020a0316821115611303575050606001516001606060020a031690565b613345615dee565b6001606060020a0382111561335657fe5b825163ffffffff16151561336657fe5b506001606060020a031660208201524363ffffffff16815290565b6133dc60a082606001516001606060020a0316901b6080836040015163ffffffff16901b602084602001516001606060020a0316901b6000856000015163ffffffff16901b171717836000191661362690919063ffffffff16565b5050565b60408051600080516020615e568339815191528152905190819003601801902060009061340c90613e6f565b1515613450576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b600160a060020a03831615156134b0576040805160e560020a62461bcd02815260206004820152601860248201527f4d494e545f544f5f5448455f5a45524f5f414444524553530000000000000000604482015290519081900360640190fd5b6134bc82610f33613eb5565b604080517f6c69646f2e53744554482e746f74616c5368617265730000000000000000000081529051908190036016019020909150613501908263ffffffff61362616565b600160a060020a03831660009081526020819052604090205461352a908363ffffffff61359816565b600160a060020a039093166000908152602081905260409020929092555090565b604080517f6c69646f2e4c69646f2e6275666665726564457468657200000000000000000081529051908190036017019020600090819061358b90613e6f565b9050303181111561153057fe5b60408051808201909152601181527f4d4154485f4144445f4f564552464c4f570000000000000000000000000000006020820152600090838301908482101561140a5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b9055565b600160a060020a03821660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef613660846121ab565b60408051918252519081900360200190a3604080518281529051600160a060020a038416916000917f9d9c909296d9c674451c0c24f02cb64981eb3b727f99865939192f880a755dcb9181900360200190a35050565b806136ed338260006040519080825280602002602001820160405280156136e7578160200160208202803883390190505b50612987565b60408051808201909152600f81527f4150505f415554485f4641494c454400000000000000000000000000000000006020820152901515612f275760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b60408051600080516020615e568339815191528152905190819003601801902061379c90613e6f565b156137f1576040805160e560020a62461bcd02815260206004820152601260248201527f434f4e54524143545f49535f4143544956450000000000000000000000000000604482015290519081900360640190fd5b60408051600080516020615e568339815191528152905190819003601801902061382290600163ffffffff61362616565b6040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f990600090a1565b60408051600080516020615e168339815191528152905190819003601401902061388d90610ed89060009061388190613242565b9063ffffffff614c9d16565b6040517fedaeeae9aed70c4545d3ab0065713261c9cee8d6cf5c8b07f52f0a65fd91efda90600090a1565b60408051600080516020615e56833981519152815290519081900360180190206138e190613e6f565b1515613925576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b60408051600080516020615e568339815191528152905190819003601801902061395690600063ffffffff61362616565b6040517f7acc84e34091ae817647a4c49116f5cc07f319078ba80f8f5fde37ea7e25cbd690600090a1565b60408051600080516020615e16833981519152815290519081900360140190206139b590610ed89060019061388190613242565b6040517f26d1807b479eaba249c1214b82e4b65bbb0cc73ee8a17901324b1ef1b5904e4990600090a1565b4390565b60408051600080516020615e5683398151915281529051908190036018019020613a0d90613e6f565b1515613a51576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b600160a060020a0383161515613ab1576040805160e560020a62461bcd02815260206004820152601960248201527f415050524f56455f46524f4d5f5a45524f5f4144445245535300000000000000604482015290519081900360640190fd5b600160a060020a0382161515613b11576040805160e560020a62461bcd02815260206004820152601760248201527f415050524f56455f544f5f5a45524f5f41444452455353000000000000000000604482015290519081900360640190fd5b600160a060020a03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600160a060020a0383161515613bd3576040805160e560020a62461bcd02815260206004820152601360248201527f4f5241434c455f5a45524f5f4144445245535300000000000000000000000000604482015290519081900360640190fd5b600160a060020a0382161515613c33576040805160e560020a62461bcd02815260206004820152601560248201527f54524541535552595f5a45524f5f414444524553530000000000000000000000604482015290519081900360640190fd5b600160a060020a0381161515613c93576040805160e560020a62461bcd02815260206004820152601b60248201527f494e535552414e43455f46554e445f5a45524f5f414444524553530000000000604482015290519081900360640190fd5b604080517f6c69646f2e4c69646f2e6f7261636c650000000000000000000000000000000081529051908190036010019020613cd5908463ffffffff61362616565b604080517f6c69646f2e4c69646f2e7472656173757279000000000000000000000000000081529051908190036012019020613d17908363ffffffff61362616565b604080517f6c69646f2e4c69646f2e696e737572616e636546756e6400000000000000000081529051908190036017019020613d59908263ffffffff61362616565b60408051600160a060020a038086168252808516602083015283168183015290517f7df55cbe17c0cf85c9c23753c046f686eeb4c6b2ce13182943d215e92afc565a9181900360600190a1505050565b613db161235d565b60408051808201909152601881527f494e49545f414c52454144595f494e495449414c495a4544000000000000000060208201529015613e365760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b50611020613e426139e0565b7febb05b386a8d34882b8711d156f463690983dc47815980fb82aeeff1aa43579e9063ffffffff61362616565b5490565b60006112ac613e80614cc2565b60408051600080516020615e3683398151915281529051908190036017019020610f3390613ead90613e6f565b610f3361354b565b604080517f6c69646f2e53744554482e746f74616c53686172657300000000000000000000815290519081900360160190206000906112ac90613e6f565b600080831515613f06576000915061268d565b50828202828482811515613f1657fe5b60408051808201909152601181527f4d4154485f4d554c5f4f564552464c4f570000000000000000000000000000006020820152929190041461140a5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b60408051808201909152600d81527f4d4154485f4449565f5a45524f00000000000000000000000000000000000000602082015260009081908184116140295760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b50828481151561403557fe5b04949350505050565b6000614049826112bb565b9050614056848483614593565b82600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a382600160a060020a031684600160a060020a03167f9d9c909296d9c674451c0c24f02cb64981eb3b727f99865939192f880a755dcb836040518082815260200191505060405180910390a350505050565b60408051808201909152601281527f4d4154485f5355425f554e444552464c4f570000000000000000000000000000602082015260009081908484111561417e5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b505050900390565b61418e615dee565b8215156141e5576040805160e560020a62461bcd02815260206004820152601460248201527f5a45524f5f4d41585f5354414b455f4c494d4954000000000000000000000000604482015290519081900360640190fd5b6001606060020a03831115614244576040805160e560020a62461bcd02815260206004820152601960248201527f544f4f5f4c415247455f4d41585f5354414b455f4c494d495400000000000000604482015290519081900360640190fd5b8183101561429c576040805160e560020a62461bcd02815260206004820152601860248201527f544f4f5f4c415247455f4c494d49545f494e4352454153450000000000000000604482015290519081900360640190fd5b8115806142b8575063ffffffff82848115156142b457fe5b0411155b151561430e576040805160e560020a62461bcd02815260206004820152601860248201527f544f4f5f534d414c4c5f4c494d49545f494e4352454153450000000000000000604482015290519081900360640190fd5b60608401516001606060020a03161580614334575083602001516001606060020a031683105b15614349576001606060020a03831660208501525b811515614357576000614364565b818381151561436257fe5b045b63ffffffff90811660408601526001606060020a0384166060860152845116156143925763ffffffff431684525b509192915050565b5490565b60006143a982613295565b156143b657506000611530565b6143bf826132a0565b15156143ce5750600019611530565b6120b7826132b2565b61271061ffff82161115614435576040805160e560020a62461bcd02815260206004820152601660248201527f56414c55455f4f5645525f3130305f50455243454e5400000000000000000000604482015290519081900360640190fd5b6133dc8261ffff831663ffffffff61362616565b600080600080600080600080600061445f612e30565b61ffff1698506144bc6144a161447b8b8d63ffffffff613ef316565b614495612710614489613e73565b9063ffffffff613ef316565b9063ffffffff6140f216565b6112f46144ac613eb5565b6144898e8e63ffffffff613ef316565b97506144c830896133e0565b506144d16120e6565b90985096506144f290506127106112f48a61ffff8b1663ffffffff613ef316565b94506144fc61126e565b9350614509308587614593565b614513848661362a565b6145356145306127106112f48b61ffff8b1663ffffffff613ef316565b614d4e565b925061454b836144958a8863ffffffff6140f216565b9150614555611741565b9050614562308284614593565b61456c818361362a565b50505050505050505050565b600160a060020a031660009081526020819052604090205490565b60408051600080516020615e56833981519152815290519081900360180190206000906145bf90613e6f565b1515614603576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b600160a060020a0384161515614663576040805160e560020a62461bcd02815260206004820152601e60248201527f5452414e534645525f46524f4d5f5448455f5a45524f5f414444524553530000604482015290519081900360640190fd5b600160a060020a03831615156146c3576040805160e560020a62461bcd02815260206004820152601c60248201527f5452414e534645525f544f5f5448455f5a45524f5f4144445245535300000000604482015290519081900360640190fd5b50600160a060020a03831660009081526020819052604090205480821115614735576040805160e560020a62461bcd02815260206004820152601f60248201527f5452414e534645525f414d4f554e545f455843454544535f42414c414e434500604482015290519081900360640190fd5b614745818363ffffffff6140f216565b600160a060020a03808616600090815260208190526040808220939093559085168152205461477a908363ffffffff61359816565b600160a060020a03909316600090815260208190526040902092909255505050565b60408051600080516020615e5683398151915281529051908190036018019020600090819081906147cc90613e6f565b1515614810576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b61481861354b565b92506801bc16d674ec800000831061487e57614832614884565b915061484d836801bc16d674ec80000063ffffffff613f9e16565b905061486e6148698583106148625785614864565b825b614f3f565b6152be565b81614877614884565b1461487e57fe5b50505050565b60006112ac61489161354b565b30319063ffffffff6140f216565b60408051600160a060020a0383166024808301919091528251808303909101815260449091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f70a0823100000000000000000000000000000000000000000000000000000000179052600090818061491f8684615339565b60408051808201909152601c81527f534146455f4552435f32305f42414c414e43455f524556455254454400000000602082015291935091508215156149aa5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b5095945050505050565b60408051600160a060020a038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905260009061318f858261536a565b8051602002815290565b614a48615dee565b506000606082015290565b6060614a6883600160a060020a0316836153b8565b9392505050565b60408051600080516020615e5683398151915281529051908190036018019020600090819081908190614aa190613e6f565b1515614ae5576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b600160a060020a0386161515614b45576040805160e560020a62461bcd02815260206004820152601a60248201527f4255524e5f46524f4d5f5448455f5a45524f5f41444452455353000000000000604482015290519081900360640190fd5b600160a060020a038616600090815260208190526040902054925082851115614bb8576040805160e560020a62461bcd02815260206004820152601b60248201527f4255524e5f414d4f554e545f455843454544535f42414c414e43450000000000604482015290519081900360640190fd5b614bc1856121ab565b9150614bcf85614495613eb5565b604080517f6c69646f2e53744554482e746f74616c5368617265730000000000000000000081529051908190036016019020909450614c14908563ffffffff61362616565b614c24838663ffffffff6140f216565b600160a060020a038716600090815260208190526040902055614c46856121ab565b60408051848152602081018390528082018890529051919250600160a060020a038816917f8b2a1e1ad5e0578c3dd82494156e985dade827a87c573b5c1c7716a32162ad649181900360600190a250505092915050565b614ca5615dee565b81614cb05743614cb3565b60005b63ffffffff1683525090919050565b60408051600080516020615e768339815191528152905190819003601d01902060009081908190614cf290613e6f565b60408051600080516020615ed68339815191528152905190819003601a019020909250614d1e90613e6f565b905080821015614d2a57fe5b614d476801bc16d674ec800000614489848463ffffffff6140f216565b9250505090565b60006060806000614d5d611412565b600160a060020a03166362dcfda1866040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015614da257600080fd5b505af1158015614db6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040908152811015614ddf57600080fd5b810190808051640100000000811115614df757600080fd5b82016020810184811115614e0a57600080fd5b8151856020820283011164010000000082111715614e2757600080fd5b50509291906020018051640100000000811115614e4357600080fd5b82016020810184811115614e5657600080fd5b8151856020820283011164010000000082111715614e7357600080fd5b50509291905050509250925081518351141515614e8c57fe5b5060009250825b8251811015610fcd57614ed5308483815181101515614eae57fe5b906020019060200201518484815181101515614ec657fe5b90602001906020020151614593565b614f0d8382815181101515614ee657fe5b906020019060200201518383815181101515614efe57fe5b9060200190602002015161362a565b614f358282815181101515614f1e57fe5b60209081029091010151859063ffffffff61359816565b9350600101614e93565b6000606080600080606080614f52611412565b600160a060020a03166341bc716f896040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015614f9757600080fd5b505af1158015614fab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040908152811015614fd457600080fd5b810190808051640100000000811115614fec57600080fd5b82016020810184811115614fff57600080fd5b815164010000000081118282018710171561501957600080fd5b5050929190602001805164010000000081111561503557600080fd5b8201602081018481111561504857600080fd5b815164010000000081118282018710171561506257600080fd5b50508451949a5098505050901515905061507f57600096506152b3565b855161509290603063ffffffff61541316565b1561510d576040805160e560020a62461bcd02815260206004820152602160248201527f52454749535452595f494e434f4e53495354454e545f5055424b4559535f4c4560448201527f4e00000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b845161512090606063ffffffff61541316565b15615175576040805160e560020a62461bcd02815260206004820152601d60248201527f52454749535452595f494e434f4e53495354454e545f5349475f4c454e000000604482015290519081900360640190fd5b855161518890603063ffffffff613f9e16565b855190945061519e90606063ffffffff613f9e16565b84146151f4576040805160e560020a62461bcd02815260206004820152601f60248201527f52454749535452595f494e434f4e53495354454e545f5349475f434f554e5400604482015290519081900360640190fd5b600092505b8383101561523857615210866030850260306154b0565b9150615221856060850260606154b0565b905061522d8282615531565b8260010192506151f9565b60408051600080516020615e768339815191528152905190819003601d0190206152979061526b908690610f3390613e6f565b60408051600080516020615e768339815191528152905190819003601d0190209063ffffffff61362616565b6152b0846801bc16d674ec80000063ffffffff613ef316565b96505b505050505050919050565b604080517f6c69646f2e4c69646f2e627566666572656445746865720000000000000000008152905190819003601701902061530390610f3f90839061449590613e6f565b6040805182815290517f76a397bea5768d4fca97ef47792796e35f98dc81b16c1de84e28a818e1f971089181900360200190a150565b6000806000806040516020818751602089018a5afa9250600083111561535e57805191505b50909590945092505050565b6000806040516020818551602087016000895af160008111156153ae573d801561539b57602081146153a4576153ac565b600193506153ac565b600183511493505b505b5090949350505050565b6040805160028082526060808301845292602083019080388339019050509050828160008151811015156153e857fe5b60209081029091010152805182908290600190811061540357fe5b6020908102909101015292915050565b60408051808201909152600d81527f4d4154485f4449565f5a45524f00000000000000000000000000000000000000602082015260009082151561549c5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b5081838115156154a857fe5b069392505050565b6060808284018551101515156154c557600080fd5b821580156154de57604051915060208201604052615528565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156155175780518352602092830192016154ff565b5050858452601f01601f1916604052505b50949350505050565b60008060008060008060006155446119d2565b965086151561559d576040805160e560020a62461bcd02815260206004820152601c60248201527f454d5054595f5749544844524157414c5f43524544454e5449414c5300000000604482015290519081900360640190fd5b6801bc16d674ec80000095506155bd86633b9aca0063ffffffff613f9e16565b9450856155d486633b9aca0063ffffffff613ef316565b146155db57fe5b60026155e68a615cab565b6040518082805190602001908083835b602083106156155780518252601f1990920191602091820191016155f6565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af1158015615656573d6000803e3d6000fd5b5050506040513d602081101561566b57600080fd5b5051935060028061567f8a600060406154b0565b6040518082805190602001908083835b602083106156ae5780518252601f19909201916020918201910161568f565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af11580156156ef573d6000803e3d6000fd5b5050506040513d602081101561570457600080fd5b5051600261572c6157278c604061572260608263ffffffff6140f216565b6154b0565b615cab565b6040518082805190602001908083835b6020831061575b5780518252601f19909201916020918201910161573c565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af115801561579c573d6000803e3d6000fd5b5050506040513d60208110156157b157600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b602083106158075780518252601f1990920191602091820191016157e8565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af1158015615848573d6000803e3d6000fd5b5050506040513d602081101561585d57600080fd5b50516040805160208181018890528183018b905282518083038401815260609092019283905281519396506002938493918291908401908083835b602083106158b75780518252601f199092019160209182019101615898565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af11580156158f8573d6000803e3d6000fd5b5050506040513d602081101561590d57600080fd5b5051600261591a88615d3b565b60408051602080820193909352808201899052815180820383018152606090910191829052805190928291908401908083835b6020831061596c5780518252601f19909201916020918201910161594d565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af11580156159ad573d6000803e3d6000fd5b5050506040513d60208110156159c257600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310615a185780518252601f1990920191602091820191016159f9565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af1158015615a59573d6000803e3d6000fd5b5050506040513d6020811015615a6e57600080fd5b50519150615a8330318763ffffffff6140f216565b9050615a8d612cab565b600160a060020a03166322895118878b8a6040516020018082600019166000191681526020019150506040516020818303038152906040528c876040518663ffffffff1660e01b8152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015615b29578181015183820152602001615b11565b50505050905090810190601f168015615b565780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015615b89578181015183820152602001615b71565b50505050905090810190601f168015615bb65780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015615be9578181015183820152602001615bd1565b50505050905090810190601f168015615c165780820380516001836020036101000a031916815260200191505b509750505050505050506000604051808303818588803b158015615c3957600080fd5b505af1158015615c4d573d6000803e3d6000fd5b50505050303182149050611f37576040805160e560020a62461bcd02815260206004820152601b60248201527f455850454354494e475f4445504f5349545f544f5f48415050454e0000000000604482015290519081900360640190fd5b6060806020835110158015615cc257506040835111155b1515615cca57fe5b825160401415615cdc57829150611303565b604080516020808252818301909252908082016104008038833901905050905060006020820152825160201415615d17576113008382615d73565b61130083615d36836000615722885160406140f290919063ffffffff16565b615d73565b600081815b6008811015615d6157600892831b60ff831617929190911c90600101615d40565b8115615d6957fe5b505060c01b919050565b6060806040519050835180825260208201818101602087015b81831015615da4578051835260209283019201615d8c565b50855184518101855292509050808201602086015b81831015615dd1578051835260209283019201615db9565b509551919091011594909401601f01601f19166040529392505050565b6040805160808101825260008082526020820181905291810182905260608101919091529056006c69646f2e4c69646f2e7374616b654c696d69740000000000000000000000006c69646f2e4c69646f2e626561636f6e42616c616e63650000000000000000006c69646f2e5061757361626c652e616374697665466c616700000000000000006c69646f2e4c69646f2e6465706f736974656456616c696461746f7273000000434f4e54524143545f49535f53544f50504544000000000000000000000000005354414b494e475f434f4e54524f4c5f524f4c450000000000000000000000006c69646f2e4c69646f2e626561636f6e56616c696461746f7273000000000000a165627a7a72305820867169b33ec290e89306c6decc0cd36d3cdb1bcb3e523992dceb5e117c92b8a90029ebb05b386a8d34882b8711d156f463690983dc47815980fb82aeeff1aa43579e

Deployed Bytecode

0x60806040526004361061037e5760003560e01c63ffffffff168063046f7da2146103e157806306fdde03146103f857806307da68f5146104825780630803fac014610497578063095ea7b3146104c0578063136dd43c146104e45780631459457a1461050b578063158626f71461054457806318160ddd14610575578063192084511461058a5780631ea7ca89146105a257806323b872dd146105b757806327a099d8146105e15780632914b9bd146105f65780632cb5f7841461064f5780632de03aa11461066a578063313ce5671461067f57806332f0a3b5146106aa578063353efdcf146106bf57806336bf3325146106d457806337cfdaca14610575578063389ed267146106e957806339509351146106fe5780633b19e84a146107225780633f683b6a14610737578063435721da1461074c57806347b714e0146107615780634ad509b21461077657806352b3af931461077e578063540bc5ea1461079357806356396715146107a8578063609c4c6c146107bd57806363c2eb53146107d257806364f9991a146107ee578063665b4b0b146108095780636bb98ad314610858578063706aa30d1461086d57806370a08231146108825780637475f913146108a3578063752f77f1146108b85780637a28fb88146108f35780637e4193c61461090b5780637e7db6e11461092c5780637f6fdac71461094d57806380afdea814610962578063833b1fce146109775780638b3dd7491461098c5780638cef3612146109a15780638e005553146109c95780638fcb4e5b146109e557806390adc83b14610a0957806395d89b4114610a215780639aaa2d1514610a365780639d4941d814610a4b578063a1658fad14610a6c578063a1903eab14610ad3578063a30448c014610ae7578063a457c2d714610afc578063a479e50814610b20578063a4d55d1d14610b35578063a6426f5f14610b4a578063a9059cbb14610b5f578063ab94276a14610b83578063ae2e353814610b98578063b3320d9a14610bcb578063b930908f14610be0578063ced72f8714610bf5578063d4aae0c414610c21578063d5002f2e14610c36578063dd62ed3e14610c4b578063de4796ed14610c72578063e73f452914610c87578063e97ee8cc14610cb4578063eb85262f14610ccc578063ecc1dcfb14610ce1578063ee7a7c0414610cf6578063f5eb42dc14610d1a578063f999c50614610d3b578063fa64ebac14610d50575b36156103d4576040805160e560020a62461bcd02815260206004820152600e60248201527f4e4f4e5f454d5054595f44415441000000000000000000000000000000000000604482015290519081900360640190fd5b6103de6000610d65565b50005b3480156103ed57600080fd5b506103f6610fd5565b005b34801561040457600080fd5b5061040d611022565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561044757818101518382015260200161042f565b50505050905090810190601f1680156104745780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561048e57600080fd5b506103f6611059565b3480156104a357600080fd5b506104ac6110a4565b604080519115158252519081900360200190f35b3480156104cc57600080fd5b506104ac600160a060020a03600435166024356110cd565b3480156104f057600080fd5b506104f96110e3565b60408051918252519081900360200190f35b34801561051757600080fd5b506103f6600160a060020a0360043581169060243581169060443581169060643581169060843516611106565b34801561055057600080fd5b5061055961126e565b60408051600160a060020a039092168252519081900360200190f35b34801561058157600080fd5b506104f96112b1565b34801561059657600080fd5b506104f96004356112bb565b3480156105ae57600080fd5b506104ac611309565b3480156105c357600080fd5b506104ac600160a060020a036004358116906024351660443561133e565b3480156105ed57600080fd5b50610559611412565b34801561060257600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526105599436949293602493928401919081908401838280828437509497506114509650505050505050565b34801561065b57600080fd5b506103f6600435602435611535565b34801561067657600080fd5b506104f96115df565b34801561068b57600080fd5b50610694611614565b6040805160ff9092168252519081900360200190f35b3480156106b657600080fd5b50610559611619565b3480156106cb57600080fd5b506104f961168e565b3480156106e057600080fd5b506104f96116c3565b3480156106f557600080fd5b506104f96116d0565b34801561070a57600080fd5b506104ac600160a060020a0360043516602435611705565b34801561072e57600080fd5b50610559611741565b34801561074357600080fd5b506104ac61177f565b34801561075857600080fd5b506104f96117b1565b34801561076d57600080fd5b506104f96117e6565b6103f66117f0565b34801561078a57600080fd5b506104f9611969565b34801561079f57600080fd5b506104f96119cd565b3480156107b457600080fd5b506104f96119d2565b3480156107c957600080fd5b506104f9611a10565b3480156107de57600080fd5b506103f661ffff60043516611a45565b3480156107fa57600080fd5b506103f6600435602435611b42565b34801561081557600080fd5b5061081e611f42565b6040805197151588529515156020880152868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b34801561086457600080fd5b506104f9611fe5565b34801561087957600080fd5b50610559612040565b34801561088e57600080fd5b506104f9600160a060020a03600435166120a4565b3480156108af57600080fd5b506103f66120bd565b3480156108c457600080fd5b506108cd6120e6565b6040805161ffff9485168152928416602084015292168183015290519081900360600190f35b3480156108ff57600080fd5b506104f96004356121ab565b34801561091757600080fd5b506103f6600160a060020a03600435166121d7565b34801561093857600080fd5b506104ac600160a060020a03600435166122b9565b34801561095957600080fd5b506104f96122bf565b34801561096e57600080fd5b506104f96122f4565b34801561098357600080fd5b5061055961231f565b34801561099857600080fd5b506104f961235d565b3480156109ad57600080fd5b506103f661ffff60043581169060243581169060443516612388565b3480156109d557600080fd5b506103f661ffff6004351661253d565b3480156109f157600080fd5b506104f9600160a060020a03600435166024356125ee565b348015610a1557600080fd5b506103f6600435612694565b348015610a2d57600080fd5b5061040d6126db565b348015610a4257600080fd5b506104f9612712565b348015610a5757600080fd5b506103f6600160a060020a0360043516612747565b348015610a7857600080fd5b5060408051602060046044358181013583810280860185019096528085526104ac958335600160a060020a03169560248035963696956064959394920192918291850190849080828437509497506129879650505050505050565b6104f9600160a060020a0360043516612ad2565b348015610af357600080fd5b506104f9612add565b348015610b0857600080fd5b506104ac600160a060020a0360043516602435612ae2565b348015610b2c57600080fd5b50610559612b7d565b348015610b4157600080fd5b506104f9612c64565b348015610b5657600080fd5b506104f9612c69565b348015610b6b57600080fd5b506104ac600160a060020a0360043516602435612c9e565b348015610b8f57600080fd5b50610559612cab565b348015610ba457600080fd5b50610bad612ce9565b60408051938452602084019290925282820152519081900360600190f35b348015610bd757600080fd5b506103f6612d71565b348015610bec57600080fd5b506104f9612dfb565b348015610c0157600080fd5b50610c0a612e30565b6040805161ffff9092168252519081900360200190f35b348015610c2d57600080fd5b50610559612e6e565b348015610c4257600080fd5b506104f9612e99565b348015610c5757600080fd5b506104f9600160a060020a0360043581169060243516612ea3565b348015610c7e57600080fd5b506104ac612ece565b348015610c9357600080fd5b506103f6600160a060020a0360043581169060243581169060443516612ee1565b348015610cc057600080fd5b506103f6600435612f2c565b348015610cd857600080fd5b506104f961303a565b348015610ced57600080fd5b506103f661306f565b348015610d0257600080fd5b506104f9600160a060020a03600435166024356130b4565b348015610d2657600080fd5b506104f9600160a060020a0360043516613198565b348015610d4757600080fd5b506103f66131a3565b348015610d5c57600080fd5b506104f96131de565b6000610d6f615dee565b600080341515610dc9576040805160e560020a62461bcd02815260206004820152600c60248201527f5a45524f5f4445504f5349540000000000000000000000000000000000000000604482015290519081900360640190fd5b60408051600080516020615e1683398151915281529051908190036014019020610df290613242565b9250610dfd83613295565b15610e52576040805160e560020a62461bcd02815260206004820152600e60248201527f5354414b494e475f504155534544000000000000000000000000000000000000604482015290519081900360640190fd5b610e5b836132a0565b15610f0457610e69836132b2565b915034821015610ec3576040805160e560020a62461bcd02815260206004820152600b60248201527f5354414b455f4c494d4954000000000000000000000000000000000000000000604482015290519081900360640190fd5b610f04610ed88434850363ffffffff61333d16565b60408051600080516020615e16833981519152815290519081900360140190209063ffffffff61338116565b610f0d346112bb565b9050801515610f195750345b610f2333826133e0565b50610f7d610f3f34610f3361354b565b9063ffffffff61359816565b604080517f6c69646f2e4c69646f2e62756666657265644574686572000000000000000000815290519081900360170190209063ffffffff61362616565b60408051348152600160a060020a0387166020820152815133927f96a25c8ce0baabc1fdefd93e9ed25d8e092a3332f3aa9a41722b5697231d1d1a928290030190a2610fc9338261362a565b8093505b505050919050565b604080517f524553554d455f524f4c450000000000000000000000000000000000000000008152905190819003600b019020611010906136b6565b611018613773565b61102061384d565b565b60408051808201909152601781527f4c6971756964207374616b656420457468657220322e30000000000000000000602082015290565b604080517f50415553455f524f4c45000000000000000000000000000000000000000000008152905190819003600a019020611094906136b6565b61109c6138b8565b611020613981565b6000806110af61235d565b905080158015906110c75750806110c46139e0565b10155b91505090565b60006110da3384846139e4565b50600192915050565b60408051600080516020615eb68339815191528152905190819003601401902081565b61110e61235d565b60408051808201909152601881527f494e49545f414c52454144595f494e495449414c495a45440000000000000000602082015290156111cf5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561119457818101518382015260200161117c565b50505050905090810190601f1680156111c15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50604080517f6c69646f2e4c69646f2e6e6f64654f70657261746f72735265676973747279008152905190819003601f019020611212908463ffffffff61362616565b604080517f6c69646f2e4c69646f2e6465706f736974436f6e74726163740000000000000081529051908190036019019020611254908663ffffffff61362616565b61125f848383613b73565b611267613da9565b5050505050565b604080517f6c69646f2e4c69646f2e696e737572616e636546756e64000000000000000000815290519081900360170190206000906112ac90613e6f565b905090565b60006112ac613e73565b6000806112c6613e73565b90508015156112d85760009150611303565b611300816112f46112e7613eb5565b869063ffffffff613ef316565b9063ffffffff613f9e16565b91505b50919050565b60408051600080516020615e16833981519152815290519081900360140190206000906112ac9061133990613242565b613295565b600160a060020a0383166000908152600160209081526040808320338452909152812054828110156113e0576040805160e560020a62461bcd02815260206004820152602160248201527f5452414e534645525f414d4f554e545f455843454544535f414c4c4f57414e4360448201527f4500000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b6113eb85858561403e565b6114058533611400848763ffffffff6140f216565b6139e4565b600191505b509392505050565b604080517f6c69646f2e4c69646f2e6e6f64654f70657261746f72735265676973747279008152905190819003601f0190206000906112ac90613e6f565b600061145a612b7d565b600160a060020a03166304bf2a7f836040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156114b557818101518382015260200161149d565b50505050905090810190601f1680156114e25780820380516001836020036101000a031916815260200191505b5092505050602060405180830381600087803b15801561150157600080fd5b505af1158015611515573d6000803e3d6000fd5b505050506040513d602081101561152b57600080fd5b505190505b919050565b60408051600080516020615eb68339815191528152905190819003601401902061155e906136b6565b60408051600080516020615e16833981519152815290519081900360140190206115a090610ed8908490849061159390613242565b919063ffffffff61418616565b604080518381526020810183905281517fce9fddf6179affa1ea7bf36d80a6bf0284e0f3b91f4b2fa6eea2af923e7fac2d929181900390910190a15050565b604080517f524553554d455f524f4c450000000000000000000000000000000000000000008152905190819003600b01902081565b601290565b6000611623612e6e565b600160a060020a03166332f0a3b56040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561165d57600080fd5b505af1158015611671573d6000803e3d6000fd5b505050506040513d602081101561168757600080fd5b5051905090565b604080517f4445504f5349545f524f4c4500000000000000000000000000000000000000008152905190819003600c01902081565b6801bc16d674ec80000081565b604080517f50415553455f524f4c45000000000000000000000000000000000000000000008152905190819003600a01902081565b336000818152600160209081526040808320600160a060020a038716845290915281205490916110da918590611400908663ffffffff61359816565b604080517f6c69646f2e4c69646f2e74726561737572790000000000000000000000000000815290519081900360120190206000906112ac90613e6f565b60408051600080516020615e56833981519152815290519081900360180190206000906117ab90613e6f565b15905090565b604080517f4d414e4147455f5749544844524157414c5f4b455900000000000000000000008152905190819003601501902081565b60006112ac61354b565b604080517f6c69646f2e4c69646f2e657865637574696f6e4c61796572526577617264735681527f61756c74000000000000000000000000000000000000000000000000000000006020820152905190819003602401902061185190613e6f565b600160a060020a0316331461186557600080fd5b604080517f6c69646f2e4c69646f2e746f74616c454c52657761726473436f6c6c6563746581527f640000000000000000000000000000000000000000000000000000000000000060208201529051908190036021019020611934906118d0903490610f3390613e6f565b604080517f6c69646f2e4c69646f2e746f74616c454c52657761726473436f6c6c6563746581527f6400000000000000000000000000000000000000000000000000000000000000602082015290519081900360210190209063ffffffff61362616565b6040805134815290517fd27f9b0c98bdee27044afa149eadcd2047d6399cb6613a45c5b87e6aca76e6b59181900360200190a1565b604080517f6c69646f2e4c69646f2e454c526577617264735769746864726177616c4c696d81527f6974000000000000000000000000000000000000000000000000000000000000602082015290519081900360220190206000906112ac90613e6f565b606081565b604080517f6c69646f2e4c69646f2e7769746864726177616c43726564656e7469616c73008152905190819003601f0190206000906112ac90613e6f565b60408051600080516020615e16833981519152815290519081900360140190206000906112ac90611a4090613242565b61439e565b604080517f5345545f454c5f524557415244535f5749544844524157414c5f4c494d49545f81527f524f4c450000000000000000000000000000000000000000000000000000000060208201529051908190036024019020611aa6906136b6565b604080517f6c69646f2e4c69646f2e454c526577617264735769746864726177616c4c696d81527f697400000000000000000000000000000000000000000000000000000000000060208201529051908190036022019020611b0890826143d7565b6040805161ffff8316815290517f166eb213129ab51688433b859b5a206403ee174774a1430f8ffb83af316161f69181900360200190a150565b6000806000806000806000611b7d6040518080600080516020615e568339815191528152506018019050604051809103902060001916613e6f565b1515611bc1576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b611bc961231f565b600160a060020a03163314611c28576040805160e560020a62461bcd02815260206004820152600f60248201527f4150505f415554485f4641494c45440000000000000000000000000000000000604482015290519081900360640190fd5b60408051600080516020615e768339815191528152905190819003601d019020611c5190613e6f565b965086891115611cab576040805160e560020a62461bcd02815260206004820152601760248201527f5245504f525445445f4d4f52455f4445504f5349544544000000000000000000604482015290519081900360640190fd5b60408051600080516020615ed68339815191528152905190819003601a019020611cd490613e6f565b955085891015611d2e576040805160e560020a62461bcd02815260206004820152601860248201527f5245504f525445445f4c4553535f56414c494441544f52530000000000000000604482015290519081900360640190fd5b611d3e898763ffffffff6140f216565b60408051600080516020615e3683398151915281529051908190036017019020909550611d8790611d6e90613e6f565b610f33876801bc16d674ec80000063ffffffff613ef316565b60408051600080516020615e3683398151915281529051908190036017019020909450611dba908963ffffffff61362616565b60408051600080516020615ed68339815191528152905190819003601a019020611dea908a63ffffffff61362616565b611df2612040565b9150600160a060020a03821615611f0557604080517f6c69646f2e4c69646f2e454c526577617264735769746864726177616c4c696d81527f697400000000000000000000000000000000000000000000000000000000000060208201529051908190036022019020600160a060020a03831690639342c8f49061271090611e7990613e6f565b611e81613e73565b02811515611e8b57fe5b046040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015611ec257600080fd5b505af1158015611ed6573d6000803e3d6000fd5b505050506040513d6020811015611eec57600080fd5b505192508215611f0557611f05610f3f84610f3361354b565b83881115611f3757611f1d888563ffffffff6140f216565b9050611f37611f32828563ffffffff61359816565b614449565b505050505050505050565b6000806000806000806000611f55615dee565b60408051600080516020615e1683398151915281529051908190036014019020611f7e90613242565b9050611f8981613295565b9750611f94816132a0565b9650611f9f8161439e565b955080606001516001606060020a03169450806040015163ffffffff16935080602001516001606060020a03169250806000015163ffffffff1691505090919293949596565b604080517f5345545f454c5f524557415244535f5749544844524157414c5f4c494d49545f81527f524f4c45000000000000000000000000000000000000000000000000000000006020820152905190819003602401902081565b604080517f6c69646f2e4c69646f2e657865637574696f6e4c61796572526577617264735681527f61756c7400000000000000000000000000000000000000000000000000000000602082015290519081900360240190206000906112ac90613e6f565b60006120b76120b283614578565b6121ab565b92915050565b60408051600080516020615eb683398151915281529051908190036014019020611018906136b6565b604080517f6c69646f2e4c69646f2e74726561737572794665650000000000000000000000815290519081900360150190206000908190819061212890613e6f565b604080517f6c69646f2e4c69646f2e696e737572616e6365466565000000000000000000008152905190819003601601902090935061216690613e6f565b604080517f6c69646f2e4c69646f2e6e6f64654f70657261746f72734665650000000000008152905190819003601a0190209092506121a490613e6f565b9050909192565b6000806121b6613eb5565b90508015156121c85760009150611303565b611300816112f46112e7613e73565b604080517f5345545f454c5f524557415244535f5641554c545f524f4c450000000000000081529051908190036019019020612212906136b6565b604080517f6c69646f2e4c69646f2e657865637574696f6e4c61796572526577617264735681527f61756c74000000000000000000000000000000000000000000000000000000006020820152905190819003602401902061227a908263ffffffff61362616565b60408051600160a060020a038316815290517f8e2d01c4cfaa88fa4d772d37e4d068deda4342bf4ef6dc4b0cf3e868be5ebb409181900360200190a150565b50600190565b604080517f4d414e4147455f50524f544f434f4c5f434f4e5452414354535f524f4c4500008152905190819003601e01902081565b60006112ac7fd625496217aa6a3453eecb9c3489dc5a53e6c67b444329ea2b2cbc9ff547639b613e6f565b604080517f6c69646f2e4c69646f2e6f7261636c6500000000000000000000000000000000815290519081900360100190206000906112ac90613e6f565b60006112ac7febb05b386a8d34882b8711d156f463690983dc47815980fb82aeeff1aa43579e613e6f565b604080517f4d414e4147455f464545000000000000000000000000000000000000000000008152905190819003600a0190206123c3906136b6565b6123e68161ffff16610f338461ffff168661ffff1661359890919063ffffffff16565b6127101461243e576040805160e560020a62461bcd02815260206004820152601060248201527f464545535f444f4e545f4144445f555000000000000000000000000000000000604482015290519081900360640190fd5b604080517f6c69646f2e4c69646f2e747265617375727946656500000000000000000000008152905190819003601501902061247a90846143d7565b604080517f6c69646f2e4c69646f2e696e737572616e636546656500000000000000000000815290519081900360160190206124b690836143d7565b604080517f6c69646f2e4c69646f2e6e6f64654f70657261746f72734665650000000000008152905190819003601a0190206124f290826143d7565b6040805161ffff8086168252808516602083015283168183015290517f034529db1bba3830b8877e116871f19c5b96ef86c739f2a05668c860c84668989181900360600190a1505050565b604080517f4d414e4147455f464545000000000000000000000000000000000000000000008152905190819003600a019020612578906136b6565b604080517f6c69646f2e4c69646f2e666565000000000000000000000000000000000000008152905190819003600d0190206125b490826143d7565b6040805161ffff8316815290517faab062e3faf62b6c9a0f8e62af66e0310e27127a8c871a67be7dd4d93de6da539181900360200190a150565b6000806125fc338585614593565b604080518481529051600160a060020a0386169133917f9d9c909296d9c674451c0c24f02cb64981eb3b727f99865939192f880a755dcb9181900360200190a3612645836121ab565b604080518281529051919250600160a060020a0386169133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef919081900360200190a38091505b5092915050565b604080517f4445504f5349545f524f4c4500000000000000000000000000000000000000008152905190819003600c0190206126cf906136b6565b6126d88161479c565b50565b60408051808201909152600581527f7374455448000000000000000000000000000000000000000000000000000000602082015290565b604080517f4d414e4147455f464545000000000000000000000000000000000000000000008152905190819003600a01902081565b6000806000612755846122b9565b15156127ab576040805160e560020a62461bcd02815260206004820152601260248201527f5245434f5645525f444953414c4c4f5745440000000000000000000000000000604482015290519081900360640190fd5b6127b3611619565b9250600160a060020a0383161515612815576040805160e560020a62461bcd02815260206004820152601260248201527f5245434f5645525f5641554c545f5a45524f0000000000000000000000000000604482015290519081900360640190fd5b600160a060020a03841615156128a95761282d614884565b915082600160a060020a03168260405160006040518083038185875af19250505015156128a4576040805160e560020a62461bcd02815260206004820152601760248201527f5245434f5645525f5452414e534645525f4641494c4544000000000000000000604482015290519081900360640190fd5b612936565b50826128c4600160a060020a0382163063ffffffff61489f16565b91506128e0600160a060020a038216848463ffffffff6149b416565b1515612936576040805160e560020a62461bcd02815260206004820152601d60248201527f5245434f5645525f544f4b454e5f5452414e534645525f4641494c4544000000604482015290519081900360640190fd5b83600160a060020a031683600160a060020a03167f596caf56044b55fb8c4ca640089bbc2b63cae3e978b851f5745cbb7c5b288e02846040518082815260200191505060405180910390a350505050565b6000806129926110a4565b15156129a1576000915061140a565b6129a9612e6e565b9050600160a060020a03811615156129c4576000915061140a565b80600160a060020a031663fdef91068630876129df88614a36565b60405163ffffffff861660e01b8152600160a060020a03808616600483019081529085166024830152604482018490526080606483019081528351608484015283519192909160a490910190602085019080838360005b83811015612a4e578181015183820152602001612a36565b50505050905090810190601f168015612a7b5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015612a9d57600080fd5b505af1158015612ab1573d6000803e3d6000fd5b505050506040513d6020811015612ac757600080fd5b505195945050505050565b60006120b782610d65565b602081565b336000908152600160209081526040808320600160a060020a038616845290915281205482811015612b5e576040805160e560020a62461bcd02815260206004820152601e60248201527f4445435245415345445f414c4c4f57414e43455f42454c4f575f5a45524f0000604482015290519081900360640190fd5b612b733385611400848763ffffffff6140f216565b5060019392505050565b600080612b88612e6e565b604080517fbe00bbd80000000000000000000000000000000000000000000000000000000081527fd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb60048201527fddbcfd564f642ab5627cf68b9b7d374fb4f8a36e941a75d89c87998cef03bd6160248201529051600160a060020a03929092169163be00bbd8916044808201926020929091908290030181600087803b158015612c3257600080fd5b505af1158015612c46573d6000803e3d6000fd5b505050506040513d6020811015612c5c57600080fd5b505192915050565b603081565b604080517f5345545f454c5f524557415244535f5641554c545f524f4c45000000000000008152905190819003601901902081565b60006110da33848461403e565b604080517f6c69646f2e4c69646f2e6465706f736974436f6e747261637400000000000000815290519081900360190190206000906112ac90613e6f565b60408051600080516020615e768339815191528152905190819003601d01902060009081908190612d1990613e6f565b60408051600080516020615ed68339815191528152905190819003601a019020909350612d4590613e6f565b60408051600080516020615e36833981519152815290519081900360170190209092506121a490613e6f565b60408051600080516020615eb683398151915281529051908190036014019020612d9a906136b6565b60408051600080516020615e1683398151915281529051908190036014019020612dd090610ed890612dcb90613242565b614a40565b6040517f9b2a687c198898fcc32a33bbc610d478f177a73ab7352023e6cc1de5bf12a3df90600090a1565b604080517f4255524e5f524f4c4500000000000000000000000000000000000000000000008152905190819003600901902081565b604080517f6c69646f2e4c69646f2e666565000000000000000000000000000000000000008152905190819003600d0190206000906112ac90613e6f565b60006112ac7f4172f0f7d2289153072b0a6ca36959e0cbe2efc3afe50fc81636caa96338137b613e6f565b60006112ac613eb5565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b6000600019612edb61235d565b14905090565b604080517f4d414e4147455f50524f544f434f4c5f434f4e5452414354535f524f4c4500008152905190819003601e019020612f1c906136b6565b612f27838383613b73565b505050565b604080517f4d414e4147455f5749544844524157414c5f4b4559000000000000000000000081529051908190036015019020612f67906136b6565b604080517f6c69646f2e4c69646f2e7769746864726177616c43726564656e7469616c73008152905190819003601f019020612fa9908263ffffffff61362616565b612fb1611412565b600160a060020a031663f778021e6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612feb57600080fd5b505af1158015612fff573d6000803e3d6000fd5b50506040805184815290517f13eb80e900aa05a2696d50d5de33ef631c73493c4921da233b17335ff6b7b1149350908190036020019150a150565b604080517f5354414b494e475f50415553455f524f4c4500000000000000000000000000008152905190819003601201902081565b604080517f4445504f5349545f524f4c4500000000000000000000000000000000000000008152905190819003600c0190206130aa906136b6565b611020609661479c565b604080517f4255524e5f524f4c450000000000000000000000000000000000000000000000815290519081900360090190206000906130f38484614a53565b6130fe338383612987565b60408051808201909152600f81527f4150505f415554485f4641494c4544000000000000000000000000000000000060208201529015156131845760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b5061318f8585614a6f565b95945050505050565b60006120b782614578565b604080517f5354414b494e475f50415553455f524f4c4500000000000000000000000000008152905190819003601201902061109c906136b6565b604080517f6c69646f2e4c69646f2e746f74616c454c52657761726473436f6c6c6563746581527f6400000000000000000000000000000000000000000000000000000000000000602082015290519081900360210190206000906112ac90613e6f565b61324a615dee565b600061325583613e6f565b63ffffffff600082901c811684526001606060020a03602083811c821690860152608083901c909116604085015260a09190911c16606083015250919050565b5163ffffffff161590565b606001516001606060020a0316151590565b6040810151600090819063ffffffff16156132f657826040015163ffffffff1683606001516001606060020a03168115156132e957fe5b046001606060020a031690505b80836000015163ffffffff1643030283602001516001606060020a031601915082606001516001606060020a0316821115611303575050606001516001606060020a031690565b613345615dee565b6001606060020a0382111561335657fe5b825163ffffffff16151561336657fe5b506001606060020a031660208201524363ffffffff16815290565b6133dc60a082606001516001606060020a0316901b6080836040015163ffffffff16901b602084602001516001606060020a0316901b6000856000015163ffffffff16901b171717836000191661362690919063ffffffff16565b5050565b60408051600080516020615e568339815191528152905190819003601801902060009061340c90613e6f565b1515613450576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b600160a060020a03831615156134b0576040805160e560020a62461bcd02815260206004820152601860248201527f4d494e545f544f5f5448455f5a45524f5f414444524553530000000000000000604482015290519081900360640190fd5b6134bc82610f33613eb5565b604080517f6c69646f2e53744554482e746f74616c5368617265730000000000000000000081529051908190036016019020909150613501908263ffffffff61362616565b600160a060020a03831660009081526020819052604090205461352a908363ffffffff61359816565b600160a060020a039093166000908152602081905260409020929092555090565b604080517f6c69646f2e4c69646f2e6275666665726564457468657200000000000000000081529051908190036017019020600090819061358b90613e6f565b9050303181111561153057fe5b60408051808201909152601181527f4d4154485f4144445f4f564552464c4f570000000000000000000000000000006020820152600090838301908482101561140a5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b9055565b600160a060020a03821660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef613660846121ab565b60408051918252519081900360200190a3604080518281529051600160a060020a038416916000917f9d9c909296d9c674451c0c24f02cb64981eb3b727f99865939192f880a755dcb9181900360200190a35050565b806136ed338260006040519080825280602002602001820160405280156136e7578160200160208202803883390190505b50612987565b60408051808201909152600f81527f4150505f415554485f4641494c454400000000000000000000000000000000006020820152901515612f275760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b60408051600080516020615e568339815191528152905190819003601801902061379c90613e6f565b156137f1576040805160e560020a62461bcd02815260206004820152601260248201527f434f4e54524143545f49535f4143544956450000000000000000000000000000604482015290519081900360640190fd5b60408051600080516020615e568339815191528152905190819003601801902061382290600163ffffffff61362616565b6040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f990600090a1565b60408051600080516020615e168339815191528152905190819003601401902061388d90610ed89060009061388190613242565b9063ffffffff614c9d16565b6040517fedaeeae9aed70c4545d3ab0065713261c9cee8d6cf5c8b07f52f0a65fd91efda90600090a1565b60408051600080516020615e56833981519152815290519081900360180190206138e190613e6f565b1515613925576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b60408051600080516020615e568339815191528152905190819003601801902061395690600063ffffffff61362616565b6040517f7acc84e34091ae817647a4c49116f5cc07f319078ba80f8f5fde37ea7e25cbd690600090a1565b60408051600080516020615e16833981519152815290519081900360140190206139b590610ed89060019061388190613242565b6040517f26d1807b479eaba249c1214b82e4b65bbb0cc73ee8a17901324b1ef1b5904e4990600090a1565b4390565b60408051600080516020615e5683398151915281529051908190036018019020613a0d90613e6f565b1515613a51576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b600160a060020a0383161515613ab1576040805160e560020a62461bcd02815260206004820152601960248201527f415050524f56455f46524f4d5f5a45524f5f4144445245535300000000000000604482015290519081900360640190fd5b600160a060020a0382161515613b11576040805160e560020a62461bcd02815260206004820152601760248201527f415050524f56455f544f5f5a45524f5f41444452455353000000000000000000604482015290519081900360640190fd5b600160a060020a03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600160a060020a0383161515613bd3576040805160e560020a62461bcd02815260206004820152601360248201527f4f5241434c455f5a45524f5f4144445245535300000000000000000000000000604482015290519081900360640190fd5b600160a060020a0382161515613c33576040805160e560020a62461bcd02815260206004820152601560248201527f54524541535552595f5a45524f5f414444524553530000000000000000000000604482015290519081900360640190fd5b600160a060020a0381161515613c93576040805160e560020a62461bcd02815260206004820152601b60248201527f494e535552414e43455f46554e445f5a45524f5f414444524553530000000000604482015290519081900360640190fd5b604080517f6c69646f2e4c69646f2e6f7261636c650000000000000000000000000000000081529051908190036010019020613cd5908463ffffffff61362616565b604080517f6c69646f2e4c69646f2e7472656173757279000000000000000000000000000081529051908190036012019020613d17908363ffffffff61362616565b604080517f6c69646f2e4c69646f2e696e737572616e636546756e6400000000000000000081529051908190036017019020613d59908263ffffffff61362616565b60408051600160a060020a038086168252808516602083015283168183015290517f7df55cbe17c0cf85c9c23753c046f686eeb4c6b2ce13182943d215e92afc565a9181900360600190a1505050565b613db161235d565b60408051808201909152601881527f494e49545f414c52454144595f494e495449414c495a4544000000000000000060208201529015613e365760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b50611020613e426139e0565b7febb05b386a8d34882b8711d156f463690983dc47815980fb82aeeff1aa43579e9063ffffffff61362616565b5490565b60006112ac613e80614cc2565b60408051600080516020615e3683398151915281529051908190036017019020610f3390613ead90613e6f565b610f3361354b565b604080517f6c69646f2e53744554482e746f74616c53686172657300000000000000000000815290519081900360160190206000906112ac90613e6f565b600080831515613f06576000915061268d565b50828202828482811515613f1657fe5b60408051808201909152601181527f4d4154485f4d554c5f4f564552464c4f570000000000000000000000000000006020820152929190041461140a5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b60408051808201909152600d81527f4d4154485f4449565f5a45524f00000000000000000000000000000000000000602082015260009081908184116140295760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b50828481151561403557fe5b04949350505050565b6000614049826112bb565b9050614056848483614593565b82600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a382600160a060020a031684600160a060020a03167f9d9c909296d9c674451c0c24f02cb64981eb3b727f99865939192f880a755dcb836040518082815260200191505060405180910390a350505050565b60408051808201909152601281527f4d4154485f5355425f554e444552464c4f570000000000000000000000000000602082015260009081908484111561417e5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b505050900390565b61418e615dee565b8215156141e5576040805160e560020a62461bcd02815260206004820152601460248201527f5a45524f5f4d41585f5354414b455f4c494d4954000000000000000000000000604482015290519081900360640190fd5b6001606060020a03831115614244576040805160e560020a62461bcd02815260206004820152601960248201527f544f4f5f4c415247455f4d41585f5354414b455f4c494d495400000000000000604482015290519081900360640190fd5b8183101561429c576040805160e560020a62461bcd02815260206004820152601860248201527f544f4f5f4c415247455f4c494d49545f494e4352454153450000000000000000604482015290519081900360640190fd5b8115806142b8575063ffffffff82848115156142b457fe5b0411155b151561430e576040805160e560020a62461bcd02815260206004820152601860248201527f544f4f5f534d414c4c5f4c494d49545f494e4352454153450000000000000000604482015290519081900360640190fd5b60608401516001606060020a03161580614334575083602001516001606060020a031683105b15614349576001606060020a03831660208501525b811515614357576000614364565b818381151561436257fe5b045b63ffffffff90811660408601526001606060020a0384166060860152845116156143925763ffffffff431684525b509192915050565b5490565b60006143a982613295565b156143b657506000611530565b6143bf826132a0565b15156143ce5750600019611530565b6120b7826132b2565b61271061ffff82161115614435576040805160e560020a62461bcd02815260206004820152601660248201527f56414c55455f4f5645525f3130305f50455243454e5400000000000000000000604482015290519081900360640190fd5b6133dc8261ffff831663ffffffff61362616565b600080600080600080600080600061445f612e30565b61ffff1698506144bc6144a161447b8b8d63ffffffff613ef316565b614495612710614489613e73565b9063ffffffff613ef316565b9063ffffffff6140f216565b6112f46144ac613eb5565b6144898e8e63ffffffff613ef316565b97506144c830896133e0565b506144d16120e6565b90985096506144f290506127106112f48a61ffff8b1663ffffffff613ef316565b94506144fc61126e565b9350614509308587614593565b614513848661362a565b6145356145306127106112f48b61ffff8b1663ffffffff613ef316565b614d4e565b925061454b836144958a8863ffffffff6140f216565b9150614555611741565b9050614562308284614593565b61456c818361362a565b50505050505050505050565b600160a060020a031660009081526020819052604090205490565b60408051600080516020615e56833981519152815290519081900360180190206000906145bf90613e6f565b1515614603576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b600160a060020a0384161515614663576040805160e560020a62461bcd02815260206004820152601e60248201527f5452414e534645525f46524f4d5f5448455f5a45524f5f414444524553530000604482015290519081900360640190fd5b600160a060020a03831615156146c3576040805160e560020a62461bcd02815260206004820152601c60248201527f5452414e534645525f544f5f5448455f5a45524f5f4144445245535300000000604482015290519081900360640190fd5b50600160a060020a03831660009081526020819052604090205480821115614735576040805160e560020a62461bcd02815260206004820152601f60248201527f5452414e534645525f414d4f554e545f455843454544535f42414c414e434500604482015290519081900360640190fd5b614745818363ffffffff6140f216565b600160a060020a03808616600090815260208190526040808220939093559085168152205461477a908363ffffffff61359816565b600160a060020a03909316600090815260208190526040902092909255505050565b60408051600080516020615e5683398151915281529051908190036018019020600090819081906147cc90613e6f565b1515614810576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b61481861354b565b92506801bc16d674ec800000831061487e57614832614884565b915061484d836801bc16d674ec80000063ffffffff613f9e16565b905061486e6148698583106148625785614864565b825b614f3f565b6152be565b81614877614884565b1461487e57fe5b50505050565b60006112ac61489161354b565b30319063ffffffff6140f216565b60408051600160a060020a0383166024808301919091528251808303909101815260449091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f70a0823100000000000000000000000000000000000000000000000000000000179052600090818061491f8684615339565b60408051808201909152601c81527f534146455f4552435f32305f42414c414e43455f524556455254454400000000602082015291935091508215156149aa5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b5095945050505050565b60408051600160a060020a038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905260009061318f858261536a565b8051602002815290565b614a48615dee565b506000606082015290565b6060614a6883600160a060020a0316836153b8565b9392505050565b60408051600080516020615e5683398151915281529051908190036018019020600090819081908190614aa190613e6f565b1515614ae5576040805160e560020a62461bcd0281526020600482015260136024820152600080516020615e96833981519152604482015290519081900360640190fd5b600160a060020a0386161515614b45576040805160e560020a62461bcd02815260206004820152601a60248201527f4255524e5f46524f4d5f5448455f5a45524f5f41444452455353000000000000604482015290519081900360640190fd5b600160a060020a038616600090815260208190526040902054925082851115614bb8576040805160e560020a62461bcd02815260206004820152601b60248201527f4255524e5f414d4f554e545f455843454544535f42414c414e43450000000000604482015290519081900360640190fd5b614bc1856121ab565b9150614bcf85614495613eb5565b604080517f6c69646f2e53744554482e746f74616c5368617265730000000000000000000081529051908190036016019020909450614c14908563ffffffff61362616565b614c24838663ffffffff6140f216565b600160a060020a038716600090815260208190526040902055614c46856121ab565b60408051848152602081018390528082018890529051919250600160a060020a038816917f8b2a1e1ad5e0578c3dd82494156e985dade827a87c573b5c1c7716a32162ad649181900360600190a250505092915050565b614ca5615dee565b81614cb05743614cb3565b60005b63ffffffff1683525090919050565b60408051600080516020615e768339815191528152905190819003601d01902060009081908190614cf290613e6f565b60408051600080516020615ed68339815191528152905190819003601a019020909250614d1e90613e6f565b905080821015614d2a57fe5b614d476801bc16d674ec800000614489848463ffffffff6140f216565b9250505090565b60006060806000614d5d611412565b600160a060020a03166362dcfda1866040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015614da257600080fd5b505af1158015614db6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040908152811015614ddf57600080fd5b810190808051640100000000811115614df757600080fd5b82016020810184811115614e0a57600080fd5b8151856020820283011164010000000082111715614e2757600080fd5b50509291906020018051640100000000811115614e4357600080fd5b82016020810184811115614e5657600080fd5b8151856020820283011164010000000082111715614e7357600080fd5b50509291905050509250925081518351141515614e8c57fe5b5060009250825b8251811015610fcd57614ed5308483815181101515614eae57fe5b906020019060200201518484815181101515614ec657fe5b90602001906020020151614593565b614f0d8382815181101515614ee657fe5b906020019060200201518383815181101515614efe57fe5b9060200190602002015161362a565b614f358282815181101515614f1e57fe5b60209081029091010151859063ffffffff61359816565b9350600101614e93565b6000606080600080606080614f52611412565b600160a060020a03166341bc716f896040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015614f9757600080fd5b505af1158015614fab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040908152811015614fd457600080fd5b810190808051640100000000811115614fec57600080fd5b82016020810184811115614fff57600080fd5b815164010000000081118282018710171561501957600080fd5b5050929190602001805164010000000081111561503557600080fd5b8201602081018481111561504857600080fd5b815164010000000081118282018710171561506257600080fd5b50508451949a5098505050901515905061507f57600096506152b3565b855161509290603063ffffffff61541316565b1561510d576040805160e560020a62461bcd02815260206004820152602160248201527f52454749535452595f494e434f4e53495354454e545f5055424b4559535f4c4560448201527f4e00000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b845161512090606063ffffffff61541316565b15615175576040805160e560020a62461bcd02815260206004820152601d60248201527f52454749535452595f494e434f4e53495354454e545f5349475f4c454e000000604482015290519081900360640190fd5b855161518890603063ffffffff613f9e16565b855190945061519e90606063ffffffff613f9e16565b84146151f4576040805160e560020a62461bcd02815260206004820152601f60248201527f52454749535452595f494e434f4e53495354454e545f5349475f434f554e5400604482015290519081900360640190fd5b600092505b8383101561523857615210866030850260306154b0565b9150615221856060850260606154b0565b905061522d8282615531565b8260010192506151f9565b60408051600080516020615e768339815191528152905190819003601d0190206152979061526b908690610f3390613e6f565b60408051600080516020615e768339815191528152905190819003601d0190209063ffffffff61362616565b6152b0846801bc16d674ec80000063ffffffff613ef316565b96505b505050505050919050565b604080517f6c69646f2e4c69646f2e627566666572656445746865720000000000000000008152905190819003601701902061530390610f3f90839061449590613e6f565b6040805182815290517f76a397bea5768d4fca97ef47792796e35f98dc81b16c1de84e28a818e1f971089181900360200190a150565b6000806000806040516020818751602089018a5afa9250600083111561535e57805191505b50909590945092505050565b6000806040516020818551602087016000895af160008111156153ae573d801561539b57602081146153a4576153ac565b600193506153ac565b600183511493505b505b5090949350505050565b6040805160028082526060808301845292602083019080388339019050509050828160008151811015156153e857fe5b60209081029091010152805182908290600190811061540357fe5b6020908102909101015292915050565b60408051808201909152600d81527f4d4154485f4449565f5a45524f00000000000000000000000000000000000000602082015260009082151561549c5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561119457818101518382015260200161117c565b5081838115156154a857fe5b069392505050565b6060808284018551101515156154c557600080fd5b821580156154de57604051915060208201604052615528565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156155175780518352602092830192016154ff565b5050858452601f01601f1916604052505b50949350505050565b60008060008060008060006155446119d2565b965086151561559d576040805160e560020a62461bcd02815260206004820152601c60248201527f454d5054595f5749544844524157414c5f43524544454e5449414c5300000000604482015290519081900360640190fd5b6801bc16d674ec80000095506155bd86633b9aca0063ffffffff613f9e16565b9450856155d486633b9aca0063ffffffff613ef316565b146155db57fe5b60026155e68a615cab565b6040518082805190602001908083835b602083106156155780518252601f1990920191602091820191016155f6565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af1158015615656573d6000803e3d6000fd5b5050506040513d602081101561566b57600080fd5b5051935060028061567f8a600060406154b0565b6040518082805190602001908083835b602083106156ae5780518252601f19909201916020918201910161568f565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af11580156156ef573d6000803e3d6000fd5b5050506040513d602081101561570457600080fd5b5051600261572c6157278c604061572260608263ffffffff6140f216565b6154b0565b615cab565b6040518082805190602001908083835b6020831061575b5780518252601f19909201916020918201910161573c565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af115801561579c573d6000803e3d6000fd5b5050506040513d60208110156157b157600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b602083106158075780518252601f1990920191602091820191016157e8565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af1158015615848573d6000803e3d6000fd5b5050506040513d602081101561585d57600080fd5b50516040805160208181018890528183018b905282518083038401815260609092019283905281519396506002938493918291908401908083835b602083106158b75780518252601f199092019160209182019101615898565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af11580156158f8573d6000803e3d6000fd5b5050506040513d602081101561590d57600080fd5b5051600261591a88615d3b565b60408051602080820193909352808201899052815180820383018152606090910191829052805190928291908401908083835b6020831061596c5780518252601f19909201916020918201910161594d565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af11580156159ad573d6000803e3d6000fd5b5050506040513d60208110156159c257600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310615a185780518252601f1990920191602091820191016159f9565b51815160209384036101000a600019018019909216911617905260405191909301945091925050808303816000865af1158015615a59573d6000803e3d6000fd5b5050506040513d6020811015615a6e57600080fd5b50519150615a8330318763ffffffff6140f216565b9050615a8d612cab565b600160a060020a03166322895118878b8a6040516020018082600019166000191681526020019150506040516020818303038152906040528c876040518663ffffffff1660e01b8152600401808060200180602001806020018560001916600019168152602001848103845288818151815260200191508051906020019080838360005b83811015615b29578181015183820152602001615b11565b50505050905090810190601f168015615b565780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015615b89578181015183820152602001615b71565b50505050905090810190601f168015615bb65780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015615be9578181015183820152602001615bd1565b50505050905090810190601f168015615c165780820380516001836020036101000a031916815260200191505b509750505050505050506000604051808303818588803b158015615c3957600080fd5b505af1158015615c4d573d6000803e3d6000fd5b50505050303182149050611f37576040805160e560020a62461bcd02815260206004820152601b60248201527f455850454354494e475f4445504f5349545f544f5f48415050454e0000000000604482015290519081900360640190fd5b6060806020835110158015615cc257506040835111155b1515615cca57fe5b825160401415615cdc57829150611303565b604080516020808252818301909252908082016104008038833901905050905060006020820152825160201415615d17576113008382615d73565b61130083615d36836000615722885160406140f290919063ffffffff16565b615d73565b600081815b6008811015615d6157600892831b60ff831617929190911c90600101615d40565b8115615d6957fe5b505060c01b919050565b6060806040519050835180825260208201818101602087015b81831015615da4578051835260209283019201615d8c565b50855184518101855292509050808201602086015b81831015615dd1578051835260209283019201615db9565b509551919091011594909401601f01601f19166040529392505050565b6040805160808101825260008082526020820181905291810182905260608101919091529056006c69646f2e4c69646f2e7374616b654c696d69740000000000000000000000006c69646f2e4c69646f2e626561636f6e42616c616e63650000000000000000006c69646f2e5061757361626c652e616374697665466c616700000000000000006c69646f2e4c69646f2e6465706f736974656456616c696461746f7273000000434f4e54524143545f49535f53544f50504544000000000000000000000000005354414b494e475f434f4e54524f4c5f524f4c450000000000000000000000006c69646f2e4c69646f2e626561636f6e56616c696461746f7273000000000000a165627a7a72305820867169b33ec290e89306c6decc0cd36d3cdb1bcb3e523992dceb5e117c92b8a90029

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
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.