ETH Price: $3,387.80 (+3.97%)

Contract

0x7c9eDAaF117d978A00cCe0B3c515c607B5097337
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
EtherFiNode

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 20000 runs

Other Settings:
default evmVersion
File 1 of 6 : EtherFiNode.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "./interfaces/IEtherFiNode.sol";
import "./interfaces/IEtherFiNodesManager.sol";
import "./interfaces/IProtocolRevenueManager.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol";

contract EtherFiNode is IEtherFiNode {
    address public etherFiNodesManager;

    // TODO: reduce the size of these varaibles
    uint256 public localRevenueIndex;
    uint256 public vestedAuctionRewards;
    string public ipfsHashForEncryptedValidatorKey;
    uint32 public exitRequestTimestamp;
    uint32 public exitTimestamp;
    uint32 public stakingStartTimestamp;
    VALIDATOR_PHASE public phase;

    //--------------------------------------------------------------------------------------
    //----------------------------------  CONSTRUCTOR   ------------------------------------
    //--------------------------------------------------------------------------------------

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        stakingStartTimestamp = type(uint32).max;
    }

    function initialize(address _etherFiNodesManager) public {
        require(stakingStartTimestamp == 0, "already initialised");
        require(_etherFiNodesManager != address(0), "No zero addresses");
        stakingStartTimestamp = uint32(block.timestamp);
        etherFiNodesManager = _etherFiNodesManager;
    }

    //--------------------------------------------------------------------------------------
    //----------------------------  STATE-CHANGING FUNCTIONS  ------------------------------
    //--------------------------------------------------------------------------------------

    /// @notice Based on the sources where they come from, the staking rewards are split into
    ///  - those from the execution layer: transaction fees and MEV
    ///  - those from the consensus layer: Pstaking rewards for attesting the state of the chain, 
    ///    proposing a new block, or being selected in a validator sync committe
    ///  To receive the rewards from the execution layer, it should have 'receive()' function.
    receive() external payable {}

    /// @notice Set the validator phase
    /// @param _phase the new phase
    function setPhase(
        VALIDATOR_PHASE _phase
    ) external onlyEtherFiNodeManagerContract {
        phase = _phase;
    }

    /// @notice Set the deposit data
    /// @param _ipfsHash the deposit data
    function setIpfsHashForEncryptedValidatorKey(
        string calldata _ipfsHash
    ) external onlyEtherFiNodeManagerContract {
        ipfsHashForEncryptedValidatorKey = _ipfsHash;
    }

    function setLocalRevenueIndex(
        uint256 _localRevenueIndex
    ) external payable onlyEtherFiNodeManagerContract {
        localRevenueIndex = _localRevenueIndex;
    }

    function setExitRequestTimestamp() external onlyEtherFiNodeManagerContract {
        require(exitRequestTimestamp == 0, "Exit request was already sent.");
        exitRequestTimestamp = uint32(block.timestamp);
    }

    function markExited(
        uint32 _exitTimestamp
    ) external onlyEtherFiNodeManagerContract {
        require(_exitTimestamp <= block.timestamp, "Invalid exit timesamp");
        phase = VALIDATOR_PHASE.EXITED;
        exitTimestamp = _exitTimestamp;
    }

    function markBeingSlahsed() external onlyEtherFiNodeManagerContract {
        phase = VALIDATOR_PHASE.BEING_SLASHED;
    }

    function receiveVestedRewardsForStakers()
        external
        payable
        onlyProtocolRevenueManagerContract
    {
        require(
            vestedAuctionRewards == 0,
            "already received the vested auction fee reward"
        );
        vestedAuctionRewards = msg.value;
    }

    function processVestedAuctionFeeWithdrawal() external onlyEtherFiNodeManagerContract {
        if (_getClaimableVestedRewards() > 0) {
            vestedAuctionRewards = 0;
        }
    }

    function moveRewardsToManager(
        uint256 _amount
    ) external onlyEtherFiNodeManagerContract {
        (bool sent, ) = payable(etherFiNodesManager).call{value: _amount}("");
        require(sent, "Failed to send Ether");
    }

    function withdrawFunds(
        address _treasury,
        uint256 _treasuryAmount,
        address _operator,
        uint256 _operatorAmount,
        address _tnftHolder,
        uint256 _tnftAmount,
        address _bnftHolder,
        uint256 _bnftAmount
    ) external onlyEtherFiNodeManagerContract {
        // the recipients of the funds must be able to receive the fund
        // For example, if it is a smart contract, 
        // they should implement either recieve() or fallback() properly
        // It's designed to prevent malicious actors from pausing the withdrawals
        bool sent;
        (sent, ) = payable(_operator).call{value: _operatorAmount}("");
        _treasuryAmount += (!sent) ? _operatorAmount : 0;
        (sent, ) = payable(_tnftHolder).call{value: _tnftAmount}("");
        _treasuryAmount += (!sent) ? _tnftAmount : 0;
        (sent, ) = payable(_bnftHolder).call{value: _bnftAmount}("");
        _treasuryAmount += (!sent) ? _bnftAmount : 0;
        (sent, ) = _treasury.call{value: _treasuryAmount}("");
        require(sent, "Failed to send Ether");
    }

    /// @notice compute the payouts for {staking, protocol} rewards and vested auction fee to the individuals
    /// @param _stakingRewards a flag to be set if the caller wants to compute the payouts for the stkaing rewards
    /// @param _protocolRewards a flag to be set if the caller wants to compute the payouts for the protocol rewards
    /// @param _vestedAuctionFee a flag to be set if the caller wants to compute the payouts for the vested auction fee
    /// @param _SRsplits the splits for the Staking Rewards
    /// @param _SRscale the scale
    /// @param _PRsplits the splits for the Protocol Rewards
    /// @param _PRscale the scale
    ///
    /// @return toNodeOperator  the payout to the Node Operator
    /// @return toTnft          the payout to the T-NFT holder
    /// @return toBnft          the payout to the B-NFT holder
    /// @return toTreasury      the payout to the Treasury
    function getRewardsPayouts(
        bool _stakingRewards,
        bool _protocolRewards,
        bool _vestedAuctionFee,
        IEtherFiNodesManager.RewardsSplit memory _SRsplits,
        uint256 _SRscale,
        IEtherFiNodesManager.RewardsSplit memory _PRsplits,
        uint256 _PRscale
    )
        public
        view
        onlyEtherFiNodeManagerContract
        returns (uint256, uint256, uint256, uint256)
    {
        uint256 operator;
        uint256 tnft;
        uint256 bnft;
        uint256 treasury;

        uint256[] memory tmps = new uint256[](4);
        if (_stakingRewards) {
            (tmps[0], tmps[1], tmps[2], tmps[3]) = getStakingRewardsPayouts(
                _SRsplits,
                _SRscale
            );
            operator += tmps[0];
            tnft += tmps[1];
            bnft += tmps[2];
            treasury += tmps[3];
        }

        if (_protocolRewards) {
            (tmps[0], tmps[1], tmps[2], tmps[3]) = getProtocolRewardsPayouts(
                _PRsplits,
                _PRscale
            );
            operator += tmps[0];
            tnft += tmps[1];
            bnft += tmps[2];
            treasury += tmps[3];
        }

        if (_vestedAuctionFee) {
            uint256 rewards = _getClaimableVestedRewards();
            uint256 toTnft = (rewards * 29) / 32;
            tnft += toTnft; // 29 / 32
            bnft += rewards - toTnft; // 3 / 32
        }

        return (operator, tnft, bnft, treasury);
    }

    /// @notice get the accrued staking rewards payouts to (toNodeOperator, toTnft, toBnft, toTreasury)
    /// @param _splits the splits for the staking rewards
    /// @param _scale the scale = SUM(_splits)
    ///
    /// @return toNodeOperator  the payout to the Node Operator
    /// @return toTnft          the payout to the T-NFT holder
    /// @return toBnft          the payout to the B-NFT holder
    /// @return toTreasury      the payout to the Treasury
    function getStakingRewardsPayouts(
        IEtherFiNodesManager.RewardsSplit memory _splits,
        uint256 _scale
    )
        public
        view
        onlyEtherFiNodeManagerContract
        returns (
            uint256 toNodeOperator,
            uint256 toTnft,
            uint256 toBnft,
            uint256 toTreasury
        )
    {
        uint256 balance = address(this).balance;
        uint256 rewards = (balance > vestedAuctionRewards)
            ? balance - vestedAuctionRewards
            : 0;
        
        if (rewards >= 32 ether) {
            rewards -= 32 ether;
        } else if (rewards >= 8 ether) {
            // In a case of Slashing, without the Oracle, the exact staking rewards cannot be computed in this case
            // Assume no staking rewards in this case.
            return (0, 0, 0, 0);
        }

        (
            uint256 operator,
            uint256 tnft,
            uint256 bnft,
            uint256 treasury
        ) = calculatePayouts(rewards, _splits, _scale);

        if (exitRequestTimestamp > 0) {
            uint256 daysPassedSinceExitRequest = _getDaysPassedSince(
                exitRequestTimestamp,
                uint32(block.timestamp)
            );
            if (daysPassedSinceExitRequest >= 14) {
                treasury += operator;
                operator = 0;
            }
        }

        return (operator, tnft, bnft, treasury);
    }

    /// @notice get the accrued protocol rewards payouts to (toNodeOperator, toTnft, toBnft, toTreasury)
    /// @param _splits the splits for the protocol rewards
    /// @param _scale the scale = SUM(_splits)
    ///
    /// @return toNodeOperator  the payout to the Node Operator
    /// @return toTnft          the payout to the T-NFT holder
    /// @return toBnft          the payout to the B-NFT holder
    /// @return toTreasury      the payout to the Treasury
    function getProtocolRewardsPayouts(
        IEtherFiNodesManager.RewardsSplit memory _splits,
        uint256 _scale
    )
        public
        view
        onlyEtherFiNodeManagerContract
        returns (
            uint256 toNodeOperator,
            uint256 toTnft,
            uint256 toBnft,
            uint256 toTreasury
        )
    {
        if (localRevenueIndex == 0) {
            return (0, 0, 0, 0);
        }
        uint256 globalRevenueIndex = IProtocolRevenueManager(
            protocolRevenueManagerAddress()
        ).globalRevenueIndex();
        uint256 rewards = globalRevenueIndex - localRevenueIndex;
        return calculatePayouts(rewards, _splits, _scale);
    }

    /// @notice compute the non exit penalty for the b-nft holder
    /// @param _principal the principal for the non exit penalty (e.g., 1 ether)
    /// @param _dailyPenalty the dailty penalty for the non exit penalty
    /// @param _exitTimestamp the exit timestamp for the validator node
    function getNonExitPenalty(
        uint128 _principal,
        uint64 _dailyPenalty,
        uint32 _exitTimestamp
    ) public view onlyEtherFiNodeManagerContract returns (uint256) {
        if (exitRequestTimestamp == 0) {
            return 0;
        }
        uint256 daysElapsed = _getDaysPassedSince(
            exitRequestTimestamp,
            _exitTimestamp
        );

        // full penalty
        if (daysElapsed > 365) {
            return _principal;
        }

        uint256 remaining = _principal;
        while (daysElapsed > 0) {
            uint256 exponent = Math.min(7, daysElapsed); // TODO: Re-calculate bounds
            remaining = (remaining * (100 - uint256(_dailyPenalty)) ** exponent) / (100 ** exponent);
            daysElapsed -= Math.min(7, daysElapsed);
        }

        return _principal - remaining;
    }

    /// @notice Given the current balance of the ether fi node after its EXIT,
    ///         Compute the payouts to {node operator, t-nft holder, b-nft holder, treasury}
    /// @param _splits the splits for the staking rewards
    /// @param _scale the scale = SUM(_splits)
    /// @param _principal the principal for the non exit penalty (e.g., 1 ether)
    /// @param _dailyPenalty the dailty penalty for the non exit penalty
    ///
    /// @return toNodeOperator  the payout to the Node Operator
    /// @return toTnft          the payout to the T-NFT holder
    /// @return toBnft          the payout to the B-NFT holder
    /// @return toTreasury      the payout to the Treasury
    function getFullWithdrawalPayouts(
        IEtherFiNodesManager.RewardsSplit memory _splits,
        uint256 _scale,
        uint128 _principal,
        uint64 _dailyPenalty
    )
        external
        view
        returns (
            uint256 toNodeOperator,
            uint256 toTnft,
            uint256 toBnft,
            uint256 toTreasury
        )
    {
        uint256 balance = address(this).balance - (vestedAuctionRewards - _getClaimableVestedRewards());
        require(
            balance >= 16 ether,
            "not enough balance for full withdrawal"
        );
        require(
            phase == VALIDATOR_PHASE.EXITED,
            "validator node is not exited"
        );

        // (toNodeOperator, toTnft, toBnft, toTreasury)
        uint256[] memory payouts = new uint256[](4);

        // Compute the payouts for the rewards = (staking rewards + vested auction fee rewards)
        // the protocol rewards must be paid off already in 'processNodeExit'
        (
            payouts[0],
            payouts[1],
            payouts[2],
            payouts[3]
        ) = getRewardsPayouts(
            true,
            false,
            true,
            _splits,
            _scale,
            _splits,
            _scale
        );
        balance -= (payouts[0] + payouts[1] + payouts[2] + payouts[3]);

        // Compute the payouts for the principals to {B, T}-NFTs
        uint256 toBnftPrincipal;
        uint256 toTnftPrincipal;
        if (balance > 31.5 ether) {
            // 31.5 ether < balance <= 32 ether
            toBnftPrincipal = balance - 30 ether;
        } else if (balance > 26 ether) {
            // 26 ether < balance <= 31.5 ether
            toBnftPrincipal = 1.5 ether;
        } else if (balance > 25.5 ether) {
            // 25.5 ether < balance <= 26 ether
            toBnftPrincipal = 1.5 ether - (26 ether - balance);
        } else {
            // 16 ether <= balance <= 25.5 ether
            toBnftPrincipal = 1 ether;
        }
        toTnftPrincipal = balance - toBnftPrincipal;
        payouts[1] += toTnftPrincipal;
        payouts[2] += toBnftPrincipal;

        // Deduct the NonExitPenalty from the payout to the B-NFT
        uint256 bnftNonExitPenalty = getNonExitPenalty(
            _principal,
            _dailyPenalty,
            exitTimestamp
        );
        payouts[2] -= bnftNonExitPenalty;

        // While the NonExitPenalty keeps growing till 1 ether,
        //  the incentive to the node operator stops growing at 0.5 ether
        //  the rest goes to the treasury
        if (bnftNonExitPenalty > 0.5 ether) {
            payouts[0] += 0.5 ether;
            payouts[3] += bnftNonExitPenalty - 0.5 ether;
        } else {
            payouts[0] += bnftNonExitPenalty;
        }

        require(
            payouts[0] + payouts[1] + payouts[2] + payouts[3] ==
                address(this).balance -
                    (vestedAuctionRewards - _getClaimableVestedRewards()),
            "Incorrect Amount"
        );
        return (payouts[0], payouts[1], payouts[2], payouts[3]);
    }

    function _getClaimableVestedRewards() internal view returns (uint256) {
        if (vestedAuctionRewards == 0) {
            return 0;
        }
        uint256 vestingPeriodInDays = IProtocolRevenueManager(
            protocolRevenueManagerAddress()
        ).auctionFeeVestingPeriodForStakersInDays();
        uint256 daysPassed = _getDaysPassedSince(
            stakingStartTimestamp,
            uint32(block.timestamp)
        );
        if (daysPassed >= vestingPeriodInDays) {
            return vestedAuctionRewards;
        } else {
            return 0;
        }
    }

    function _getDaysPassedSince(
        uint32 _startTimestamp,
        uint32 _endTimestamp
    ) internal pure returns (uint256) {
        if (_endTimestamp <= _startTimestamp) {
            return 0;
        }
        uint256 timeElapsed = _endTimestamp - _startTimestamp;
        return uint256(timeElapsed / (24 * 3_600));
    }

    function calculatePayouts(
        uint256 _totalAmount,
        IEtherFiNodesManager.RewardsSplit memory _splits,
        uint256 _scale
    ) public pure returns (uint256, uint256, uint256, uint256) {
        require(
            _splits.nodeOperator +
                _splits.tnft +
                _splits.bnft +
                _splits.treasury ==
                _scale,
            "Incorrect Splits"
        );
        uint256 operator = (_totalAmount * _splits.nodeOperator) / _scale;
        uint256 tnft = (_totalAmount * _splits.tnft) / _scale;
        uint256 bnft = (_totalAmount * _splits.bnft) / _scale;
        uint256 treasury = _totalAmount - (bnft + tnft + operator);
        return (operator, tnft, bnft, treasury);
    }

    function protocolRevenueManagerAddress() internal view returns (address) {
        return
            IEtherFiNodesManager(etherFiNodesManager)
                .protocolRevenueManagerContract();
    }

    function implementation() external view returns (address) {
        bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1);
        address implementation;
        assembly {
            implementation := sload(slot)
        }

        IBeacon beacon = IBeacon(implementation);
        return beacon.implementation();
    }

    //--------------------------------------------------------------------------------------
    //-----------------------------------  MODIFIERS  --------------------------------------
    //--------------------------------------------------------------------------------------

    modifier onlyEtherFiNodeManagerContract() {
        require(
            msg.sender == etherFiNodesManager,
            "Only EtherFiNodeManager Contract"
        );
        _;
    }

    modifier onlyProtocolRevenueManagerContract() {
        require(
            msg.sender == protocolRevenueManagerAddress(),
            "Only protocol revenue manager contract function"
        );
        _;
    }
}

File 2 of 6 : IEtherFiNode.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "./IEtherFiNodesManager.sol";

interface IEtherFiNode {
    //The state of the validator
    enum VALIDATOR_PHASE {
        NOT_INITIALIZED,
        STAKE_DEPOSITED,
        LIVE,
        EXITED,
        CANCELLED,
        BEING_SLASHED
    }

    // VIEW functions
    function phase() external view returns (VALIDATOR_PHASE);

    function ipfsHashForEncryptedValidatorKey()
        external
        view
        returns (string memory);

    function localRevenueIndex() external view returns (uint256);

    function stakingStartTimestamp() external view returns (uint32);

    function exitRequestTimestamp() external view returns (uint32);

    function exitTimestamp() external view returns (uint32);

    function vestedAuctionRewards() external view returns (uint256);

    function getNonExitPenalty(
        uint128 _principal,
        uint64 _dailyPenalty,
        uint32 _endTimestamp
    ) external view returns (uint256);

    function calculatePayouts(
        uint256 _totalAmount,
        IEtherFiNodesManager.RewardsSplit memory _splits,
        uint256 _scale
    ) external view returns (uint256, uint256, uint256, uint256);

    function getStakingRewardsPayouts(
        IEtherFiNodesManager.RewardsSplit memory _splits,
        uint256 _scale
    ) external view returns (uint256, uint256, uint256, uint256);

    function getProtocolRewardsPayouts(
        IEtherFiNodesManager.RewardsSplit memory _splits,
        uint256 _scale
    ) external view returns (uint256, uint256, uint256, uint256);

    function getRewardsPayouts(
        bool _stakingRewards,
        bool _protocolRewards,
        bool _vestedAuctionFee,
        IEtherFiNodesManager.RewardsSplit memory _SRsplits,
        uint256 _SRscale,
        IEtherFiNodesManager.RewardsSplit memory _PRsplits,
        uint256 _PRscale
    ) external view returns (uint256, uint256, uint256, uint256);

    function getFullWithdrawalPayouts(
        IEtherFiNodesManager.RewardsSplit memory _splits,
        uint256 _scale,
        uint128 _principal,
        uint64 _dailyPenalty
    ) external view returns (uint256, uint256, uint256, uint256);

    // Non-VIEW functions
    function setPhase(VALIDATOR_PHASE _phase) external;

    function setIpfsHashForEncryptedValidatorKey(
        string calldata _ipfs
    ) external;

    function setLocalRevenueIndex(uint256 _localRevenueIndex) external payable;

    function setExitRequestTimestamp() external;

    function markExited(uint32 _exitTimestamp) external;

    function markBeingSlahsed() external;

    function receiveVestedRewardsForStakers() external payable;

    function processVestedAuctionFeeWithdrawal() external;

    // Withdraw Rewards
    function moveRewardsToManager(uint256 _amount) external;

    function withdrawFunds(
        address _treasury,
        uint256 _treasuryAmount,
        address _operator,
        uint256 _operatorAmount,
        address _tnftHolder,
        uint256 _tnftAmount,
        address _bnftHolder,
        uint256 _bnftAmount
    ) external;
}

File 3 of 6 : IEtherFiNodesManager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "./IEtherFiNode.sol";

interface IEtherFiNodesManager {
    enum ValidatorRecipientType {
        TNFTHOLDER,
        BNFTHOLDER,
        TREASURY,
        OPERATOR
    }

    struct RewardsSplit {
        uint64 treasury;
        uint64 nodeOperator;
        uint64 tnft;
        uint64 bnft;
    }

    // VIEW functions
    function numberOfValidators() external view returns (uint64);

    function etherfiNodeAddress(
        uint256 _validatorId
    ) external view returns (address);

    function phase(
        uint256 _validatorId
    ) external view returns (IEtherFiNode.VALIDATOR_PHASE phase);

    function ipfsHashForEncryptedValidatorKey(
        uint256 _validatorId
    ) external view returns (string memory);

    function localRevenueIndex(uint256 _validatorId) external returns (uint256);

    function vestedAuctionRewards(
        uint256 _validatorId
    ) external returns (uint256);

    function generateWithdrawalCredentials(
        address _address
    ) external view returns (bytes memory);

    function getWithdrawalCredentials(
        uint256 _validatorId
    ) external view returns (bytes memory);

    function isExitRequested(uint256 _validatorId) external view returns (bool);

    function isExited(uint256 _validatorId) external view returns (bool);

    function getNonExitPenalty(
        uint256 _validatorId,
        uint32 _endTimestamp
    ) external view returns (uint256);

    function getStakingRewardsPayouts(
        uint256 _validatorId
    ) external view returns (uint256, uint256, uint256, uint256);

    function getRewardsPayouts(
        uint256 _validatorId,
        bool _stakingRewards,
        bool _protocolRewards,
        bool _vestedAuctionFee
    ) external view returns (uint256, uint256, uint256, uint256);

    function getFullWithdrawalPayouts(
        uint256 _validatorId
    ) external view returns (uint256, uint256, uint256, uint256);

    function protocolRevenueManagerContract() external view returns (address);

    // Non-VIEW functions
    function initialize(
        address _treasuryContract,
        address _auctionContract,
        address _stakingManagerContract,
        address _tnftContract,
        address _bnftContract,
        address _protocolRevenueManagerContract
    ) external;

    function incrementNumberOfValidators(uint64 _count) external;

    function registerEtherFiNode(
        uint256 _validatorId,
        address _address
    ) external;

    function unregisterEtherFiNode(uint256 _validatorId) external;

    function setStakingRewardsSplit(
        uint64 _treasury,
        uint64 _nodeOperator,
        uint64 _tnft,
        uint64 _bnft
    ) external;

    function setProtocolRewardsSplit(
        uint64 _treasury,
        uint64 _nodeOperator,
        uint64 _tnft,
        uint64 _bnft
    ) external;

    function setNonExitPenaltyPrincipal(
        uint64 _nonExitPenaltyPrincipal
    ) external;

    function setNonExitPenaltyDailyRate(
        uint64 _nonExitPenaltyDailyRate
    ) external;

    function setEtherFiNodePhase(
        uint256 _validatorId,
        IEtherFiNode.VALIDATOR_PHASE _phase
    ) external;

    function setEtherFiNodeIpfsHashForEncryptedValidatorKey(
        uint256 _validatorId,
        string calldata _ipfs
    ) external;

    function setEtherFiNodeLocalRevenueIndex(
        uint256 _validatorId,
        uint256 _localRevenueIndex
    ) external payable;

    function sendExitRequest(uint256 _validatorId) external;
    function batchSendExitRequest(uint256[] calldata _validatorIds) external;

    function processNodeExit(
        uint256[] calldata _validatorIds,
        uint32[] calldata _exitTimestamp
    ) external;

    function partialWithdraw(
        uint256 _validatorId,
        bool _stakingRewards,
        bool _protocolRewards,
        bool _vestedAuctionFee
    ) external;

    function partialWithdrawBatch(
        uint256[] calldata _validatorIds,
        bool _stakingRewards,
        bool _protocolRewards,
        bool _vestedAuctionFee
    ) external;

    function partialWithdrawBatchGroupByOperator(
        address _operator,
        uint256[] memory _validatorIds,
        bool _stakingRewards,
        bool _protocolRewards,
        bool _vestedAuctionFee
    ) external;

    function fullWithdraw(uint256 _validatorId) external;

    function fullWithdrawBatch(uint256[] calldata _validatorIds) external;
}

File 4 of 6 : IProtocolRevenueManager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IProtocolRevenueManager {
    struct AuctionRevenueSplit {
        uint64 treasurySplit;
        uint64 nodeOperatorSplit;
        uint64 tnftHolderSplit;
        uint64 bnftHolderSplit;
    }

    function globalRevenueIndex() external view returns (uint256);

    function auctionFeeVestingPeriodForStakersInDays()
        external
        view
        returns (uint128);

    function getAccruedAuctionRevenueRewards(
        uint256 _validatorId
    ) external view returns (uint256);

    function addAuctionRevenue(uint256 _validatorId) external payable;

    function distributeAuctionRevenue(
        uint256 _validatorId
    ) external returns (uint256);

    function setEtherFiNodesManagerAddress(
        address _etherFiNodesManager
    ) external;

    function setAuctionManagerAddress(address _auctionManager) external;

    function setAuctionRewardVestingPeriod(uint128 _periodInDays) external;

    function setAuctionRewardSplitForStakers(uint128 _split) external;
}

File 5 of 6 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

File 6 of 6 : IBeacon.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)

pragma solidity ^0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeacon {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}

Settings
{
  "remappings": [
    "@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "@openzeppelin/=lib/openzeppelin-contracts/",
    "@uniswap/=lib/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "murky/=lib/murky/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "safe-contracts/=lib/safe-tools/lib/safe-contracts/contracts/",
    "safe-tools/=lib/safe-tools/src/",
    "solady/=lib/safe-tools/lib/solady/src/",
    "solmate/=lib/safe-tools/lib/solady/lib/solmate/src/",
    "v3-core/=lib/v3-core/",
    "v3-periphery/=lib/v3-periphery/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 20000
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"_totalAmount","type":"uint256"},{"components":[{"internalType":"uint64","name":"treasury","type":"uint64"},{"internalType":"uint64","name":"nodeOperator","type":"uint64"},{"internalType":"uint64","name":"tnft","type":"uint64"},{"internalType":"uint64","name":"bnft","type":"uint64"}],"internalType":"struct IEtherFiNodesManager.RewardsSplit","name":"_splits","type":"tuple"},{"internalType":"uint256","name":"_scale","type":"uint256"}],"name":"calculatePayouts","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"etherFiNodesManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exitRequestTimestamp","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exitTimestamp","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"treasury","type":"uint64"},{"internalType":"uint64","name":"nodeOperator","type":"uint64"},{"internalType":"uint64","name":"tnft","type":"uint64"},{"internalType":"uint64","name":"bnft","type":"uint64"}],"internalType":"struct IEtherFiNodesManager.RewardsSplit","name":"_splits","type":"tuple"},{"internalType":"uint256","name":"_scale","type":"uint256"},{"internalType":"uint128","name":"_principal","type":"uint128"},{"internalType":"uint64","name":"_dailyPenalty","type":"uint64"}],"name":"getFullWithdrawalPayouts","outputs":[{"internalType":"uint256","name":"toNodeOperator","type":"uint256"},{"internalType":"uint256","name":"toTnft","type":"uint256"},{"internalType":"uint256","name":"toBnft","type":"uint256"},{"internalType":"uint256","name":"toTreasury","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"_principal","type":"uint128"},{"internalType":"uint64","name":"_dailyPenalty","type":"uint64"},{"internalType":"uint32","name":"_exitTimestamp","type":"uint32"}],"name":"getNonExitPenalty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"treasury","type":"uint64"},{"internalType":"uint64","name":"nodeOperator","type":"uint64"},{"internalType":"uint64","name":"tnft","type":"uint64"},{"internalType":"uint64","name":"bnft","type":"uint64"}],"internalType":"struct IEtherFiNodesManager.RewardsSplit","name":"_splits","type":"tuple"},{"internalType":"uint256","name":"_scale","type":"uint256"}],"name":"getProtocolRewardsPayouts","outputs":[{"internalType":"uint256","name":"toNodeOperator","type":"uint256"},{"internalType":"uint256","name":"toTnft","type":"uint256"},{"internalType":"uint256","name":"toBnft","type":"uint256"},{"internalType":"uint256","name":"toTreasury","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_stakingRewards","type":"bool"},{"internalType":"bool","name":"_protocolRewards","type":"bool"},{"internalType":"bool","name":"_vestedAuctionFee","type":"bool"},{"components":[{"internalType":"uint64","name":"treasury","type":"uint64"},{"internalType":"uint64","name":"nodeOperator","type":"uint64"},{"internalType":"uint64","name":"tnft","type":"uint64"},{"internalType":"uint64","name":"bnft","type":"uint64"}],"internalType":"struct IEtherFiNodesManager.RewardsSplit","name":"_SRsplits","type":"tuple"},{"internalType":"uint256","name":"_SRscale","type":"uint256"},{"components":[{"internalType":"uint64","name":"treasury","type":"uint64"},{"internalType":"uint64","name":"nodeOperator","type":"uint64"},{"internalType":"uint64","name":"tnft","type":"uint64"},{"internalType":"uint64","name":"bnft","type":"uint64"}],"internalType":"struct IEtherFiNodesManager.RewardsSplit","name":"_PRsplits","type":"tuple"},{"internalType":"uint256","name":"_PRscale","type":"uint256"}],"name":"getRewardsPayouts","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"treasury","type":"uint64"},{"internalType":"uint64","name":"nodeOperator","type":"uint64"},{"internalType":"uint64","name":"tnft","type":"uint64"},{"internalType":"uint64","name":"bnft","type":"uint64"}],"internalType":"struct IEtherFiNodesManager.RewardsSplit","name":"_splits","type":"tuple"},{"internalType":"uint256","name":"_scale","type":"uint256"}],"name":"getStakingRewardsPayouts","outputs":[{"internalType":"uint256","name":"toNodeOperator","type":"uint256"},{"internalType":"uint256","name":"toTnft","type":"uint256"},{"internalType":"uint256","name":"toBnft","type":"uint256"},{"internalType":"uint256","name":"toTreasury","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_etherFiNodesManager","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ipfsHashForEncryptedValidatorKey","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"localRevenueIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"markBeingSlahsed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_exitTimestamp","type":"uint32"}],"name":"markExited","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"moveRewardsToManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"phase","outputs":[{"internalType":"enum IEtherFiNode.VALIDATOR_PHASE","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"processVestedAuctionFeeWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"receiveVestedRewardsForStakers","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"setExitRequestTimestamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_ipfsHash","type":"string"}],"name":"setIpfsHashForEncryptedValidatorKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_localRevenueIndex","type":"uint256"}],"name":"setLocalRevenueIndex","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"enum IEtherFiNode.VALIDATOR_PHASE","name":"_phase","type":"uint8"}],"name":"setPhase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingStartTimestamp","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestedAuctionRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"uint256","name":"_treasuryAmount","type":"uint256"},{"internalType":"address","name":"_operator","type":"address"},{"internalType":"uint256","name":"_operatorAmount","type":"uint256"},{"internalType":"address","name":"_tnftHolder","type":"address"},{"internalType":"uint256","name":"_tnftAmount","type":"uint256"},{"internalType":"address","name":"_bnftHolder","type":"address"},{"internalType":"uint256","name":"_bnftAmount","type":"uint256"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234801561001057600080fd5b506004805463ffffffff60401b19166bffffffff0000000000000000179055612a658061003e6000396000f3fe6080604052600436106101a55760003560e01c80637618ebbf116100e1578063c03afb591161008a578063c7fd170b11610064578063c7fd170b146104ac578063d1e3d5ba146104cc578063d742d6cb146104ec578063dbf75eda1461050c57600080fd5b8063c03afb5914610457578063c4d66de814610477578063c5bd77c01461049757600080fd5b8063acfc28f2116100bb578063acfc28f2146103e9578063b1c9fe6e1461040b578063bbf1e9971461044257600080fd5b80637618ebbf14610397578063940d559d146103ac578063a0be6dcf146103c957600080fd5b806335369dc41161014e5780635c60da1b116101285780635c60da1b146102ff5780635ec08baf146103145780636b8ee3181461034e5780637402a85d1461036e57600080fd5b806335369dc41461029757806346c9f30b1461029f5780634720dc46146102df57600080fd5b80632c8160b01161017f5780632c8160b01461024b5780632cab108b146102615780632e57fd5b1461028157600080fd5b8063089acd98146101b15780631bb2ca17146102085780631f0535b91461023657600080fd5b366101ac57005b600080fd5b3480156101bd57600080fd5b506000546101de9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021457600080fd5b5061022861022336600461226f565b61052c565b6040519081526020016101ff565b6102496102443660046122b4565b61069c565b005b34801561025757600080fd5b5061022860015481565b34801561026d57600080fd5b5061024961027c3660046122ef565b610708565b34801561028d57600080fd5b5061022860025481565b6102496109a3565b3480156102ab57600080fd5b506102bf6102ba36600461242b565b610ac7565b6040805194855260208501939093529183015260608201526080016101ff565b3480156102eb57600080fd5b506102bf6102fa3660046124a8565b610e18565b34801561030b57600080fd5b506101de6113e7565b34801561032057600080fd5b5060045461033990640100000000900463ffffffff1681565b60405163ffffffff90911681526020016101ff565b34801561035a57600080fd5b506102bf6103693660046124f8565b61149c565b34801561037a57600080fd5b506004546103399068010000000000000000900463ffffffff1681565b3480156103a357600080fd5b506102496115ee565b3480156103b857600080fd5b506004546103399063ffffffff1681565b3480156103d557600080fd5b506102496103e4366004612523565b61166d565b3480156103f557600080fd5b506103fe6116e5565b6040516101ff9190612595565b34801561041757600080fd5b50600454610435906c01000000000000000000000000900460ff1681565b6040516101ff9190612637565b34801561044e57600080fd5b50610249611773565b34801561046357600080fd5b50610249610472366004612678565b611813565b34801561048357600080fd5b50610249610492366004612699565b6118cb565b3480156104a357600080fd5b50610249611a12565b3480156104b857600080fd5b506102496104c73660046126b6565b611b01565b3480156104d857600080fd5b506102bf6104e73660046124f8565b611c0d565b3480156104f857600080fd5b506102496105073660046122b4565b611d3f565b34801561051857600080fd5b506102bf6105273660046126d1565b611e5a565b6000805473ffffffffffffffffffffffffffffffffffffffff1633146105995760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e747261637460448201526064015b60405180910390fd5b60045463ffffffff166000036105b157506000610695565b6004546000906105c79063ffffffff1684611f99565b905061016d8111156105ed5750506fffffffffffffffffffffffffffffffff8316610695565b6fffffffffffffffffffffffffffffffff85165b8115610674576000610614600784611fe1565b9050610621816064612856565b8161063767ffffffffffffffff89166064612862565b6106419190612856565b61064b9084612879565b61065591906128b6565b9150610662600784611fe1565b61066c9084612862565b925050610601565b610690816fffffffffffffffffffffffffffffffff8816612862565b925050505b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107035760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b600155565b60005473ffffffffffffffffffffffffffffffffffffffff16331461076f5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b60008673ffffffffffffffffffffffffffffffffffffffff168660405160006040518083038185875af1925050503d80600081146107c9576040519150601f19603f3d011682016040523d82523d6000602084013e6107ce565b606091505b509091505080156107e05760006107e2565b855b6107ec90896128f1565b97508473ffffffffffffffffffffffffffffffffffffffff168460405160006040518083038185875af1925050503d8060008114610846576040519150601f19603f3d011682016040523d82523d6000602084013e61084b565b606091505b5090915050801561085d57600061085f565b835b61086990896128f1565b97508273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146108c3576040519150601f19603f3d011682016040523d82523d6000602084013e6108c8565b606091505b509091505080156108da5760006108dc565b815b6108e690896128f1565b97508873ffffffffffffffffffffffffffffffffffffffff168860405160006040518083038185875af1925050503d8060008114610940576040519150601f19603f3d011682016040523d82523d6000602084013e610945565b606091505b505080915050806109985760405162461bcd60e51b815260206004820152601460248201527f4661696c656420746f2073656e642045746865720000000000000000000000006044820152606401610590565b505050505050505050565b6109ab611ff7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a4b5760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792070726f746f636f6c20726576656e7565206d616e6167657220636f60448201527f6e74726163742066756e6374696f6e00000000000000000000000000000000006064820152608401610590565b60025415610ac15760405162461bcd60e51b815260206004820152602e60248201527f616c72656164792072656365697665642074686520766573746564206175637460448201527f696f6e20666565207265776172640000000000000000000000000000000000006064820152608401610590565b34600255565b6000805481908190819073ffffffffffffffffffffffffffffffffffffffff163314610b355760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b60408051600480825260a082019092526000918291829182918291602082016080803683370190505090508f15610c8857610b708d8d61149c565b84600081518110610b8357610b83612909565b6020026020010185600181518110610b9d57610b9d612909565b6020026020010186600281518110610bb757610bb7612909565b6020026020010187600381518110610bd157610bd1612909565b6020908102919091010193909352929091529190525280518190600090610bfa57610bfa612909565b602002602001015185610c0d91906128f1565b945080600181518110610c2257610c22612909565b602002602001015184610c3591906128f1565b935080600281518110610c4a57610c4a612909565b602002602001015183610c5d91906128f1565b925080600381518110610c7257610c72612909565b602002602001015182610c8591906128f1565b91505b8e15610db057610c988b8b611c0d565b84600081518110610cab57610cab612909565b6020026020010185600181518110610cc557610cc5612909565b6020026020010186600281518110610cdf57610cdf612909565b6020026020010187600381518110610cf957610cf9612909565b6020908102919091010193909352929091529190525280518190600090610d2257610d22612909565b602002602001015185610d3591906128f1565b945080600181518110610d4a57610d4a612909565b602002602001015184610d5d91906128f1565b935080600281518110610d7257610d72612909565b602002602001015183610d8591906128f1565b925080600381518110610d9a57610d9a612909565b602002602001015182610dad91906128f1565b91505b8d15610e02576000610dc061208e565b905060006020610dd183601d612879565b610ddb91906128b6565b9050610de781876128f1565b9550610df38183612862565b610dfd90866128f1565b945050505b50929e919d509b50909950975050505050505050565b6000806000806000610e2861208e565b600254610e359190612862565b610e3f9047612862565b905067de0b6b3a76400000811015610ebf5760405162461bcd60e51b815260206004820152602660248201527f6e6f7420656e6f7567682062616c616e636520666f722066756c6c207769746860448201527f64726177616c00000000000000000000000000000000000000000000000000006064820152608401610590565b60036004546c01000000000000000000000000900460ff166005811115610ee857610ee8612608565b14610f355760405162461bcd60e51b815260206004820152601c60248201527f76616c696461746f72206e6f6465206973206e6f7420657869746564000000006044820152606401610590565b60408051600480825260a0820190925260009160208201608080368337019050509050610f6a6001600060018d8d8f8f610ac7565b84600081518110610f7d57610f7d612909565b6020026020010185600181518110610f9757610f97612909565b6020026020010186600281518110610fb157610fb1612909565b6020026020010187600381518110610fcb57610fcb612909565b60209081029190910101939093529290915291905252805181906003908110610ff657610ff6612909565b60200260200101518160028151811061101157611011612909565b60200260200101518260018151811061102c5761102c612909565b60200260200101518360008151811061104757611047612909565b602002602001015161105991906128f1565b61106391906128f1565b61106d91906128f1565b6110779083612862565b91506000806801b5267b1b18ce00008411156110a7576110a06801a055690d9db8000085612862565b915061110a565b680168d28e3f002800008411156110c8576714d1120d7b160000915061110a565b680161e232e52c7600008411156110fe576110ec84680168d28e3f00280000612862565b6110a0906714d1120d7b160000612862565b670de0b6b3a764000091505b6111148285612862565b9050808360018151811061112a5761112a612909565b6020026020010181815161113e91906128f1565b905250825182908490600290811061115857611158612909565b6020026020010181815161116c91906128f1565b905250600454600090611190908c908c90640100000000900463ffffffff1661052c565b905080846002815181106111a6576111a6612909565b602002602001018181516111ba9190612862565b9052506706f05b59d3b20000811115611241576706f05b59d3b20000846000815181106111e9576111e9612909565b602002602001018181516111fd91906128f1565b9052506112126706f05b59d3b2000082612862565b8460038151811061122557611225612909565b6020026020010181815161123991906128f1565b90525061126d565b808460008151811061125557611255612909565b6020026020010181815161126991906128f1565b9052505b61127561208e565b6002546112829190612862565b61128c9047612862565b8460038151811061129f5761129f612909565b6020026020010151856002815181106112ba576112ba612909565b6020026020010151866001815181106112d5576112d5612909565b6020026020010151876000815181106112f0576112f0612909565b602002602001015161130291906128f1565b61130c91906128f1565b61131691906128f1565b146113635760405162461bcd60e51b815260206004820152601060248201527f496e636f727265637420416d6f756e74000000000000000000000000000000006044820152606401610590565b8360008151811061137657611376612909565b60200260200101518460018151811061139157611391612909565b6020026020010151856002815181106113ac576113ac612909565b6020026020010151866003815181106113c7576113c7612909565b602002602001015198509850985098505050505050945094509450949050565b60008061141560017fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d51612862565b60001b905060008154905060008190508073ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611470573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114949190612938565b935050505090565b6000805481908190819073ffffffffffffffffffffffffffffffffffffffff16331461150a5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b6002544790600090821161151f57600061152c565b60025461152c9083612862565b90506801bc16d674ec8000008110611558576115516801bc16d674ec80000082612862565b905061157c565b676f05b59d3b200000811061157c57600080600080955095509550955050506115e5565b60008060008061158d858d8d611e5a565b6004549397509195509350915063ffffffff16156115d8576004546000906115bb9063ffffffff1642611f99565b9050600e81106115d6576115cf85836128f1565b9150600094505b505b9298509096509450925050505b92959194509250565b60005473ffffffffffffffffffffffffffffffffffffffff1633146116555760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b600061165f61208e565b111561166b5760006002555b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146116d45760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b6116e060038383612166565b505050565b600380546116f290612955565b80601f016020809104026020016040519081016040528092919081815260200182805461171e90612955565b801561176b5780601f106117405761010080835404028352916020019161176b565b820191906000526020600020905b81548152906001019060200180831161174e57829003601f168201915b505050505081565b60005473ffffffffffffffffffffffffffffffffffffffff1633146117da5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b600480547fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff166c05000000000000000000000000179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331461187a5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b600480548291907fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff166c010000000000000000000000008360058111156118c3576118c3612608565b021790555050565b60045468010000000000000000900463ffffffff161561192d5760405162461bcd60e51b815260206004820152601360248201527f616c726561647920696e697469616c69736564000000000000000000000000006044820152606401610590565b73ffffffffffffffffffffffffffffffffffffffff81166119905760405162461bcd60e51b815260206004820152601160248201527f4e6f207a65726f206164647265737365730000000000000000000000000000006044820152606401610590565b600480547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16680100000000000000004263ffffffff1602179055600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314611a795760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b60045463ffffffff1615611acf5760405162461bcd60e51b815260206004820152601e60248201527f4578697420726571756573742077617320616c72656164792073656e742e00006044820152606401610590565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000164263ffffffff16179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314611b685760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b428163ffffffff161115611bbe5760405162461bcd60e51b815260206004820152601560248201527f496e76616c696420657869742074696d6573616d7000000000000000000000006044820152606401610590565b600480546c0300000000000000000000000063ffffffff93909316640100000000027fffffffffffffffffffffffffffffffffffffff00ffffffff00000000ffffffff90911617919091179055565b6000805481908190819073ffffffffffffffffffffffffffffffffffffffff163314611c7b5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b600154600003611c96575060009250829150819050806115e5565b6000611ca0611ff7565b73ffffffffffffffffffffffffffffffffffffffff166366f8a32b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0e91906129a8565b9050600060015482611d209190612862565b9050611d2d818989611e5a565b929b919a509850909650945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611da65760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b6000805460405173ffffffffffffffffffffffffffffffffffffffff9091169083908381818185875af1925050503d8060008114611e00576040519150601f19603f3d011682016040523d82523d6000602084013e611e05565b606091505b5050905080611e565760405162461bcd60e51b815260206004820152601460248201527f4661696c656420746f2073656e642045746865720000000000000000000000006044820152606401610590565b5050565b600080600080848660000151876060015188604001518960200151611e7f91906129c1565b611e8991906129c1565b611e9391906129c1565b67ffffffffffffffff1614611eea5760405162461bcd60e51b815260206004820152601060248201527f496e636f72726563742053706c697473000000000000000000000000000000006044820152606401610590565b600085876020015167ffffffffffffffff1689611f079190612879565b611f1191906128b6565b9050600086886040015167ffffffffffffffff168a611f309190612879565b611f3a91906128b6565b9050600087896060015167ffffffffffffffff168b611f599190612879565b611f6391906128b6565b9050600083611f7284846128f1565b611f7c91906128f1565b611f86908c612862565b939b929a50909850919650945050505050565b60008263ffffffff168263ffffffff1611611fb657506000611fdb565b6000611fc284846129ed565b63ffffffff169050611fd762015180826128b6565b9150505b92915050565b6000818310611ff05781610695565b5090919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166359435fe76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612065573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120899190612938565b905090565b60006002546000036120a05750600090565b60006120aa611ff7565b73ffffffffffffffffffffffffffffffffffffffff1663e9c074586040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121189190612a12565b6fffffffffffffffffffffffffffffffff169050600061214a600460089054906101000a900463ffffffff1642611f99565b905081811061215d576002549250505090565b60009250505090565b82805461217290612955565b90600052602060002090601f01602090048101928261219457600085556121f8565b82601f106121cb578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008235161785556121f8565b828001600101855582156121f8579182015b828111156121f85782358255916020019190600101906121dd565b50612204929150612208565b5090565b5b808211156122045760008155600101612209565b6fffffffffffffffffffffffffffffffff8116811461223b57600080fd5b50565b803567ffffffffffffffff8116811461225657600080fd5b919050565b803563ffffffff8116811461225657600080fd5b60008060006060848603121561228457600080fd5b833561228f8161221d565b925061229d6020850161223e565b91506122ab6040850161225b565b90509250925092565b6000602082840312156122c657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461223b57600080fd5b600080600080600080600080610100898b03121561230c57600080fd5b8835612317816122cd565b975060208901359650604089013561232e816122cd565b9550606089013594506080890135612345816122cd565b935060a0890135925060c089013561235c816122cd565b8092505060e089013590509295985092959890939650565b8035801515811461225657600080fd5b60006080828403121561239657600080fd5b6040516080810181811067ffffffffffffffff821117156123e0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806123ef8361223e565b81526123fd6020840161223e565b602082015261240e6040840161223e565b604082015261241f6060840161223e565b60608201525092915050565b60008060008060008060006101a0888a03121561244757600080fd5b61245088612374565b965061245e60208901612374565b955061246c60408901612374565b945061247b8960608a01612384565b935060e08801359250612492896101008a01612384565b9150610180880135905092959891949750929550565b60008060008060e085870312156124be57600080fd5b6124c88686612384565b93506080850135925060a08501356124df8161221d565b91506124ed60c0860161223e565b905092959194509250565b60008060a0838503121561250b57600080fd5b6125158484612384565b946080939093013593505050565b6000806020838503121561253657600080fd5b823567ffffffffffffffff8082111561254e57600080fd5b818501915085601f83011261256257600080fd5b81358181111561257157600080fd5b86602082850101111561258357600080fd5b60209290920196919550909350505050565b600060208083528351808285015260005b818110156125c2578581018301518582016040015282016125a6565b818111156125d4576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160068310612672577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60006020828403121561268a57600080fd5b81356006811061069557600080fd5b6000602082840312156126ab57600080fd5b8135610695816122cd565b6000602082840312156126c857600080fd5b6106958261225b565b600080600060c084860312156126e657600080fd5b833592506126f78560208601612384565b915060a084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600181815b8085111561278f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561277557612775612707565b8085161561278257918102915b93841c939080029061273b565b509250929050565b6000826127a657506001611fdb565b816127b357506000611fdb565b81600181146127c957600281146127d3576127ef565b6001915050611fdb565b60ff8411156127e4576127e4612707565b50506001821b611fdb565b5060208310610133831016604e8410600b8410161715612812575081810a611fdb565b61281c8383612736565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561284e5761284e612707565b029392505050565b60006106958383612797565b60008282101561287457612874612707565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156128b1576128b1612707565b500290565b6000826128ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000821982111561290457612904612707565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561294a57600080fd5b8151610695816122cd565b600181811c9082168061296957607f821691505b6020821081036129a2577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b6000602082840312156129ba57600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156129e4576129e4612707565b01949350505050565b600063ffffffff83811690831681811015612a0a57612a0a612707565b039392505050565b600060208284031215612a2457600080fd5b81516106958161221d56fea2646970667358221220905c18f9d6d4e1b6ed1411572cdc43f9f542673c32c71d3951c87a0018002fd064736f6c634300080d0033

Deployed Bytecode

0x6080604052600436106101a55760003560e01c80637618ebbf116100e1578063c03afb591161008a578063c7fd170b11610064578063c7fd170b146104ac578063d1e3d5ba146104cc578063d742d6cb146104ec578063dbf75eda1461050c57600080fd5b8063c03afb5914610457578063c4d66de814610477578063c5bd77c01461049757600080fd5b8063acfc28f2116100bb578063acfc28f2146103e9578063b1c9fe6e1461040b578063bbf1e9971461044257600080fd5b80637618ebbf14610397578063940d559d146103ac578063a0be6dcf146103c957600080fd5b806335369dc41161014e5780635c60da1b116101285780635c60da1b146102ff5780635ec08baf146103145780636b8ee3181461034e5780637402a85d1461036e57600080fd5b806335369dc41461029757806346c9f30b1461029f5780634720dc46146102df57600080fd5b80632c8160b01161017f5780632c8160b01461024b5780632cab108b146102615780632e57fd5b1461028157600080fd5b8063089acd98146101b15780631bb2ca17146102085780631f0535b91461023657600080fd5b366101ac57005b600080fd5b3480156101bd57600080fd5b506000546101de9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021457600080fd5b5061022861022336600461226f565b61052c565b6040519081526020016101ff565b6102496102443660046122b4565b61069c565b005b34801561025757600080fd5b5061022860015481565b34801561026d57600080fd5b5061024961027c3660046122ef565b610708565b34801561028d57600080fd5b5061022860025481565b6102496109a3565b3480156102ab57600080fd5b506102bf6102ba36600461242b565b610ac7565b6040805194855260208501939093529183015260608201526080016101ff565b3480156102eb57600080fd5b506102bf6102fa3660046124a8565b610e18565b34801561030b57600080fd5b506101de6113e7565b34801561032057600080fd5b5060045461033990640100000000900463ffffffff1681565b60405163ffffffff90911681526020016101ff565b34801561035a57600080fd5b506102bf6103693660046124f8565b61149c565b34801561037a57600080fd5b506004546103399068010000000000000000900463ffffffff1681565b3480156103a357600080fd5b506102496115ee565b3480156103b857600080fd5b506004546103399063ffffffff1681565b3480156103d557600080fd5b506102496103e4366004612523565b61166d565b3480156103f557600080fd5b506103fe6116e5565b6040516101ff9190612595565b34801561041757600080fd5b50600454610435906c01000000000000000000000000900460ff1681565b6040516101ff9190612637565b34801561044e57600080fd5b50610249611773565b34801561046357600080fd5b50610249610472366004612678565b611813565b34801561048357600080fd5b50610249610492366004612699565b6118cb565b3480156104a357600080fd5b50610249611a12565b3480156104b857600080fd5b506102496104c73660046126b6565b611b01565b3480156104d857600080fd5b506102bf6104e73660046124f8565b611c0d565b3480156104f857600080fd5b506102496105073660046122b4565b611d3f565b34801561051857600080fd5b506102bf6105273660046126d1565b611e5a565b6000805473ffffffffffffffffffffffffffffffffffffffff1633146105995760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e747261637460448201526064015b60405180910390fd5b60045463ffffffff166000036105b157506000610695565b6004546000906105c79063ffffffff1684611f99565b905061016d8111156105ed5750506fffffffffffffffffffffffffffffffff8316610695565b6fffffffffffffffffffffffffffffffff85165b8115610674576000610614600784611fe1565b9050610621816064612856565b8161063767ffffffffffffffff89166064612862565b6106419190612856565b61064b9084612879565b61065591906128b6565b9150610662600784611fe1565b61066c9084612862565b925050610601565b610690816fffffffffffffffffffffffffffffffff8816612862565b925050505b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107035760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b600155565b60005473ffffffffffffffffffffffffffffffffffffffff16331461076f5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b60008673ffffffffffffffffffffffffffffffffffffffff168660405160006040518083038185875af1925050503d80600081146107c9576040519150601f19603f3d011682016040523d82523d6000602084013e6107ce565b606091505b509091505080156107e05760006107e2565b855b6107ec90896128f1565b97508473ffffffffffffffffffffffffffffffffffffffff168460405160006040518083038185875af1925050503d8060008114610846576040519150601f19603f3d011682016040523d82523d6000602084013e61084b565b606091505b5090915050801561085d57600061085f565b835b61086990896128f1565b97508273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146108c3576040519150601f19603f3d011682016040523d82523d6000602084013e6108c8565b606091505b509091505080156108da5760006108dc565b815b6108e690896128f1565b97508873ffffffffffffffffffffffffffffffffffffffff168860405160006040518083038185875af1925050503d8060008114610940576040519150601f19603f3d011682016040523d82523d6000602084013e610945565b606091505b505080915050806109985760405162461bcd60e51b815260206004820152601460248201527f4661696c656420746f2073656e642045746865720000000000000000000000006044820152606401610590565b505050505050505050565b6109ab611ff7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a4b5760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792070726f746f636f6c20726576656e7565206d616e6167657220636f60448201527f6e74726163742066756e6374696f6e00000000000000000000000000000000006064820152608401610590565b60025415610ac15760405162461bcd60e51b815260206004820152602e60248201527f616c72656164792072656365697665642074686520766573746564206175637460448201527f696f6e20666565207265776172640000000000000000000000000000000000006064820152608401610590565b34600255565b6000805481908190819073ffffffffffffffffffffffffffffffffffffffff163314610b355760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b60408051600480825260a082019092526000918291829182918291602082016080803683370190505090508f15610c8857610b708d8d61149c565b84600081518110610b8357610b83612909565b6020026020010185600181518110610b9d57610b9d612909565b6020026020010186600281518110610bb757610bb7612909565b6020026020010187600381518110610bd157610bd1612909565b6020908102919091010193909352929091529190525280518190600090610bfa57610bfa612909565b602002602001015185610c0d91906128f1565b945080600181518110610c2257610c22612909565b602002602001015184610c3591906128f1565b935080600281518110610c4a57610c4a612909565b602002602001015183610c5d91906128f1565b925080600381518110610c7257610c72612909565b602002602001015182610c8591906128f1565b91505b8e15610db057610c988b8b611c0d565b84600081518110610cab57610cab612909565b6020026020010185600181518110610cc557610cc5612909565b6020026020010186600281518110610cdf57610cdf612909565b6020026020010187600381518110610cf957610cf9612909565b6020908102919091010193909352929091529190525280518190600090610d2257610d22612909565b602002602001015185610d3591906128f1565b945080600181518110610d4a57610d4a612909565b602002602001015184610d5d91906128f1565b935080600281518110610d7257610d72612909565b602002602001015183610d8591906128f1565b925080600381518110610d9a57610d9a612909565b602002602001015182610dad91906128f1565b91505b8d15610e02576000610dc061208e565b905060006020610dd183601d612879565b610ddb91906128b6565b9050610de781876128f1565b9550610df38183612862565b610dfd90866128f1565b945050505b50929e919d509b50909950975050505050505050565b6000806000806000610e2861208e565b600254610e359190612862565b610e3f9047612862565b905067de0b6b3a76400000811015610ebf5760405162461bcd60e51b815260206004820152602660248201527f6e6f7420656e6f7567682062616c616e636520666f722066756c6c207769746860448201527f64726177616c00000000000000000000000000000000000000000000000000006064820152608401610590565b60036004546c01000000000000000000000000900460ff166005811115610ee857610ee8612608565b14610f355760405162461bcd60e51b815260206004820152601c60248201527f76616c696461746f72206e6f6465206973206e6f7420657869746564000000006044820152606401610590565b60408051600480825260a0820190925260009160208201608080368337019050509050610f6a6001600060018d8d8f8f610ac7565b84600081518110610f7d57610f7d612909565b6020026020010185600181518110610f9757610f97612909565b6020026020010186600281518110610fb157610fb1612909565b6020026020010187600381518110610fcb57610fcb612909565b60209081029190910101939093529290915291905252805181906003908110610ff657610ff6612909565b60200260200101518160028151811061101157611011612909565b60200260200101518260018151811061102c5761102c612909565b60200260200101518360008151811061104757611047612909565b602002602001015161105991906128f1565b61106391906128f1565b61106d91906128f1565b6110779083612862565b91506000806801b5267b1b18ce00008411156110a7576110a06801a055690d9db8000085612862565b915061110a565b680168d28e3f002800008411156110c8576714d1120d7b160000915061110a565b680161e232e52c7600008411156110fe576110ec84680168d28e3f00280000612862565b6110a0906714d1120d7b160000612862565b670de0b6b3a764000091505b6111148285612862565b9050808360018151811061112a5761112a612909565b6020026020010181815161113e91906128f1565b905250825182908490600290811061115857611158612909565b6020026020010181815161116c91906128f1565b905250600454600090611190908c908c90640100000000900463ffffffff1661052c565b905080846002815181106111a6576111a6612909565b602002602001018181516111ba9190612862565b9052506706f05b59d3b20000811115611241576706f05b59d3b20000846000815181106111e9576111e9612909565b602002602001018181516111fd91906128f1565b9052506112126706f05b59d3b2000082612862565b8460038151811061122557611225612909565b6020026020010181815161123991906128f1565b90525061126d565b808460008151811061125557611255612909565b6020026020010181815161126991906128f1565b9052505b61127561208e565b6002546112829190612862565b61128c9047612862565b8460038151811061129f5761129f612909565b6020026020010151856002815181106112ba576112ba612909565b6020026020010151866001815181106112d5576112d5612909565b6020026020010151876000815181106112f0576112f0612909565b602002602001015161130291906128f1565b61130c91906128f1565b61131691906128f1565b146113635760405162461bcd60e51b815260206004820152601060248201527f496e636f727265637420416d6f756e74000000000000000000000000000000006044820152606401610590565b8360008151811061137657611376612909565b60200260200101518460018151811061139157611391612909565b6020026020010151856002815181106113ac576113ac612909565b6020026020010151866003815181106113c7576113c7612909565b602002602001015198509850985098505050505050945094509450949050565b60008061141560017fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d51612862565b60001b905060008154905060008190508073ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611470573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114949190612938565b935050505090565b6000805481908190819073ffffffffffffffffffffffffffffffffffffffff16331461150a5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b6002544790600090821161151f57600061152c565b60025461152c9083612862565b90506801bc16d674ec8000008110611558576115516801bc16d674ec80000082612862565b905061157c565b676f05b59d3b200000811061157c57600080600080955095509550955050506115e5565b60008060008061158d858d8d611e5a565b6004549397509195509350915063ffffffff16156115d8576004546000906115bb9063ffffffff1642611f99565b9050600e81106115d6576115cf85836128f1565b9150600094505b505b9298509096509450925050505b92959194509250565b60005473ffffffffffffffffffffffffffffffffffffffff1633146116555760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b600061165f61208e565b111561166b5760006002555b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146116d45760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b6116e060038383612166565b505050565b600380546116f290612955565b80601f016020809104026020016040519081016040528092919081815260200182805461171e90612955565b801561176b5780601f106117405761010080835404028352916020019161176b565b820191906000526020600020905b81548152906001019060200180831161174e57829003601f168201915b505050505081565b60005473ffffffffffffffffffffffffffffffffffffffff1633146117da5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b600480547fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff166c05000000000000000000000000179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331461187a5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b600480548291907fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff166c010000000000000000000000008360058111156118c3576118c3612608565b021790555050565b60045468010000000000000000900463ffffffff161561192d5760405162461bcd60e51b815260206004820152601360248201527f616c726561647920696e697469616c69736564000000000000000000000000006044820152606401610590565b73ffffffffffffffffffffffffffffffffffffffff81166119905760405162461bcd60e51b815260206004820152601160248201527f4e6f207a65726f206164647265737365730000000000000000000000000000006044820152606401610590565b600480547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16680100000000000000004263ffffffff1602179055600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314611a795760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b60045463ffffffff1615611acf5760405162461bcd60e51b815260206004820152601e60248201527f4578697420726571756573742077617320616c72656164792073656e742e00006044820152606401610590565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000164263ffffffff16179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314611b685760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b428163ffffffff161115611bbe5760405162461bcd60e51b815260206004820152601560248201527f496e76616c696420657869742074696d6573616d7000000000000000000000006044820152606401610590565b600480546c0300000000000000000000000063ffffffff93909316640100000000027fffffffffffffffffffffffffffffffffffffff00ffffffff00000000ffffffff90911617919091179055565b6000805481908190819073ffffffffffffffffffffffffffffffffffffffff163314611c7b5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b600154600003611c96575060009250829150819050806115e5565b6000611ca0611ff7565b73ffffffffffffffffffffffffffffffffffffffff166366f8a32b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0e91906129a8565b9050600060015482611d209190612862565b9050611d2d818989611e5a565b929b919a509850909650945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611da65760405162461bcd60e51b815260206004820181905260248201527f4f6e6c7920457468657246694e6f64654d616e6167657220436f6e74726163746044820152606401610590565b6000805460405173ffffffffffffffffffffffffffffffffffffffff9091169083908381818185875af1925050503d8060008114611e00576040519150601f19603f3d011682016040523d82523d6000602084013e611e05565b606091505b5050905080611e565760405162461bcd60e51b815260206004820152601460248201527f4661696c656420746f2073656e642045746865720000000000000000000000006044820152606401610590565b5050565b600080600080848660000151876060015188604001518960200151611e7f91906129c1565b611e8991906129c1565b611e9391906129c1565b67ffffffffffffffff1614611eea5760405162461bcd60e51b815260206004820152601060248201527f496e636f72726563742053706c697473000000000000000000000000000000006044820152606401610590565b600085876020015167ffffffffffffffff1689611f079190612879565b611f1191906128b6565b9050600086886040015167ffffffffffffffff168a611f309190612879565b611f3a91906128b6565b9050600087896060015167ffffffffffffffff168b611f599190612879565b611f6391906128b6565b9050600083611f7284846128f1565b611f7c91906128f1565b611f86908c612862565b939b929a50909850919650945050505050565b60008263ffffffff168263ffffffff1611611fb657506000611fdb565b6000611fc284846129ed565b63ffffffff169050611fd762015180826128b6565b9150505b92915050565b6000818310611ff05781610695565b5090919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166359435fe76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612065573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120899190612938565b905090565b60006002546000036120a05750600090565b60006120aa611ff7565b73ffffffffffffffffffffffffffffffffffffffff1663e9c074586040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121189190612a12565b6fffffffffffffffffffffffffffffffff169050600061214a600460089054906101000a900463ffffffff1642611f99565b905081811061215d576002549250505090565b60009250505090565b82805461217290612955565b90600052602060002090601f01602090048101928261219457600085556121f8565b82601f106121cb578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008235161785556121f8565b828001600101855582156121f8579182015b828111156121f85782358255916020019190600101906121dd565b50612204929150612208565b5090565b5b808211156122045760008155600101612209565b6fffffffffffffffffffffffffffffffff8116811461223b57600080fd5b50565b803567ffffffffffffffff8116811461225657600080fd5b919050565b803563ffffffff8116811461225657600080fd5b60008060006060848603121561228457600080fd5b833561228f8161221d565b925061229d6020850161223e565b91506122ab6040850161225b565b90509250925092565b6000602082840312156122c657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461223b57600080fd5b600080600080600080600080610100898b03121561230c57600080fd5b8835612317816122cd565b975060208901359650604089013561232e816122cd565b9550606089013594506080890135612345816122cd565b935060a0890135925060c089013561235c816122cd565b8092505060e089013590509295985092959890939650565b8035801515811461225657600080fd5b60006080828403121561239657600080fd5b6040516080810181811067ffffffffffffffff821117156123e0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806123ef8361223e565b81526123fd6020840161223e565b602082015261240e6040840161223e565b604082015261241f6060840161223e565b60608201525092915050565b60008060008060008060006101a0888a03121561244757600080fd5b61245088612374565b965061245e60208901612374565b955061246c60408901612374565b945061247b8960608a01612384565b935060e08801359250612492896101008a01612384565b9150610180880135905092959891949750929550565b60008060008060e085870312156124be57600080fd5b6124c88686612384565b93506080850135925060a08501356124df8161221d565b91506124ed60c0860161223e565b905092959194509250565b60008060a0838503121561250b57600080fd5b6125158484612384565b946080939093013593505050565b6000806020838503121561253657600080fd5b823567ffffffffffffffff8082111561254e57600080fd5b818501915085601f83011261256257600080fd5b81358181111561257157600080fd5b86602082850101111561258357600080fd5b60209290920196919550909350505050565b600060208083528351808285015260005b818110156125c2578581018301518582016040015282016125a6565b818111156125d4576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160068310612672577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60006020828403121561268a57600080fd5b81356006811061069557600080fd5b6000602082840312156126ab57600080fd5b8135610695816122cd565b6000602082840312156126c857600080fd5b6106958261225b565b600080600060c084860312156126e657600080fd5b833592506126f78560208601612384565b915060a084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600181815b8085111561278f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561277557612775612707565b8085161561278257918102915b93841c939080029061273b565b509250929050565b6000826127a657506001611fdb565b816127b357506000611fdb565b81600181146127c957600281146127d3576127ef565b6001915050611fdb565b60ff8411156127e4576127e4612707565b50506001821b611fdb565b5060208310610133831016604e8410600b8410161715612812575081810a611fdb565b61281c8383612736565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561284e5761284e612707565b029392505050565b60006106958383612797565b60008282101561287457612874612707565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156128b1576128b1612707565b500290565b6000826128ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000821982111561290457612904612707565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561294a57600080fd5b8151610695816122cd565b600181811c9082168061296957607f821691505b6020821081036129a2577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b6000602082840312156129ba57600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156129e4576129e4612707565b01949350505050565b600063ffffffff83811690831681811015612a0a57612a0a612707565b039392505050565b600060208284031215612a2457600080fd5b81516106958161221d56fea2646970667358221220905c18f9d6d4e1b6ed1411572cdc43f9f542673c32c71d3951c87a0018002fd064736f6c634300080d0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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.