ETH Price: $3,259.06 (+1.13%)

Contract

0x842DDfE3F5caDfd45c45421329CDDf0Af994940e
 

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:
RewardsManager

Compiler Version
v0.7.4+commit.3f05b770

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 15 : RewardsManager.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;
pragma experimental ABIEncoderV2;

import "@openzeppelin/contracts/math/SafeMath.sol";

import "../upgrades/GraphUpgradeable.sol";

import "./RewardsManagerStorage.sol";
import "./IRewardsManager.sol";

contract RewardsManager is RewardsManagerV1Storage, GraphUpgradeable, IRewardsManager {
    using SafeMath for uint256;

    uint256 private constant TOKEN_DECIMALS = 1e18;
    uint256 private constant MIN_ISSUANCE_RATE = 1e18;

    // -- Events --

    /**
     * @dev Emitted when rewards are assigned to an indexer.
     */
    event RewardsAssigned(
        address indexed indexer,
        address indexed allocationID,
        uint256 epoch,
        uint256 amount
    );

    /**
     * @dev Emitted when rewards are denied to an indexer.
     */
    event RewardsDenied(address indexed indexer, address indexed allocationID, uint256 epoch);

    /**
     * @dev Emitted when a subgraph is denied for claiming rewards.
     */
    event RewardsDenylistUpdated(bytes32 indexed subgraphDeploymentID, uint256 sinceBlock);

    // -- Modifiers --

    modifier onlySubgraphAvailabilityOracle() {
        require(
            msg.sender == address(subgraphAvailabilityOracle),
            "Caller must be the subgraph availability oracle"
        );
        _;
    }

    /**
     * @dev Initialize this contract.
     */
    function initialize(address _controller, uint256 _issuanceRate) external onlyImpl {
        Managed._initialize(_controller);

        // Settings
        _setIssuanceRate(_issuanceRate);
    }

    /**
     * @dev Sets the issuance rate.
     * The issuance rate is defined as a percentage increase of the total supply per block.
     * This means that it needs to be greater than 1.0, any number under 1.0 is not
     * allowed and an issuance rate of 1.0 means no issuance.
     * To accommodate a high precision the issuance rate is expressed in wei.
     * @param _issuanceRate Issuance rate expressed in wei
     */
    function setIssuanceRate(uint256 _issuanceRate) external override onlyGovernor {
        _setIssuanceRate(_issuanceRate);
    }

    /**
     * @dev Sets the issuance rate.
     * @param _issuanceRate Issuance rate
     */
    function _setIssuanceRate(uint256 _issuanceRate) private {
        require(_issuanceRate >= MIN_ISSUANCE_RATE, "Issuance rate under minimum allowed");

        // Called since `issuance rate` will change
        updateAccRewardsPerSignal();

        issuanceRate = _issuanceRate;
        emit ParameterUpdated("issuanceRate");
    }

    /**
     * @dev Sets the subgraph oracle allowed to denegate distribution of rewards to subgraphs.
     * @param _subgraphAvailabilityOracle Address of the subgraph availability oracle
     */
    function setSubgraphAvailabilityOracle(address _subgraphAvailabilityOracle)
        external
        override
        onlyGovernor
    {
        subgraphAvailabilityOracle = _subgraphAvailabilityOracle;
        emit ParameterUpdated("subgraphAvailabilityOracle");
    }

    /**
     * @dev Denies to claim rewards for a subgraph.
     * NOTE: Can only be called by the subgraph availability oracle
     * @param _subgraphDeploymentID Subgraph deployment ID
     * @param _deny Whether to set the subgraph as denied for claiming rewards or not
     */
    function setDenied(bytes32 _subgraphDeploymentID, bool _deny)
        external
        override
        onlySubgraphAvailabilityOracle
    {
        _setDenied(_subgraphDeploymentID, _deny);
    }

    /**
     * @dev Denies to claim rewards for multiple subgraph.
     * NOTE: Can only be called by the subgraph availability oracle
     * @param _subgraphDeploymentID Array of subgraph deployment ID
     * @param _deny Array of denied status for claiming rewards for each subgraph
     */
    function setDeniedMany(bytes32[] calldata _subgraphDeploymentID, bool[] calldata _deny)
        external
        override
        onlySubgraphAvailabilityOracle
    {
        require(_subgraphDeploymentID.length == _deny.length, "!length");
        for (uint256 i = 0; i < _subgraphDeploymentID.length; i++) {
            _setDenied(_subgraphDeploymentID[i], _deny[i]);
        }
    }

    /**
     * @dev Internal: Denies to claim rewards for a subgraph.
     * @param _subgraphDeploymentID Subgraph deployment ID
     * @param _deny Whether to set the subgraph as denied for claiming rewards or not
     */
    function _setDenied(bytes32 _subgraphDeploymentID, bool _deny) private {
        uint256 sinceBlock = _deny ? block.number : 0;
        denylist[_subgraphDeploymentID] = sinceBlock;
        emit RewardsDenylistUpdated(_subgraphDeploymentID, sinceBlock);
    }

    /**
     * @dev Tells if subgraph is in deny list
     * @param _subgraphDeploymentID Subgraph deployment ID to check
     */
    function isDenied(bytes32 _subgraphDeploymentID) public override view returns (bool) {
        return denylist[_subgraphDeploymentID] > 0;
    }

    /**
     * @dev Gets the issuance of rewards per signal since last updated.
     *
     * Compound interest formula: `a = p(1 + r/n)^nt`
     * The formula is simplified with `n = 1` as we apply the interest once every time step.
     * The `r` is passed with +1 included. So for 10% instead of 0.1 it is 1.1
     * The simplified formula is `a = p * r^t`
     *
     * Notation:
     * t: time steps are in blocks since last updated
     * p: total supply of GRT tokens
     * a: inflated amount of total supply for the period `t` when interest `r` is applied
     * x: newly accrued rewards token for the period `t`
     *
     * @return newly accrued rewards per signal since last update
     */
    function getNewRewardsPerSignal() public override view returns (uint256) {
        // Calculate time steps
        uint256 t = block.number.sub(accRewardsPerSignalLastBlockUpdated);
        // Optimization to skip calculations if zero time steps elapsed
        if (t == 0) {
            return 0;
        }

        // Zero issuance under a rate of 1.0
        if (issuanceRate <= MIN_ISSUANCE_RATE) {
            return 0;
        }

        // Zero issuance if no signalled tokens
        IGraphToken graphToken = graphToken();
        uint256 signalledTokens = graphToken.balanceOf(address(curation()));
        if (signalledTokens == 0) {
            return 0;
        }

        uint256 r = issuanceRate;
        uint256 p = graphToken.totalSupply();
        uint256 a = p.mul(_pow(r, t, TOKEN_DECIMALS)).div(TOKEN_DECIMALS);

        // New issuance per signalled token during time steps
        uint256 x = a.sub(p);

        // We multiply the decimals to keep the precision as fixed-point number
        return x.mul(TOKEN_DECIMALS).div(signalledTokens);
    }

    /**
     * @dev Gets the currently accumulated rewards per signal.
     */
    function getAccRewardsPerSignal() public override view returns (uint256) {
        return accRewardsPerSignal.add(getNewRewardsPerSignal());
    }

    /**
     * @dev Gets the accumulated rewards for the subgraph.
     * @param _subgraphDeploymentID Subgraph deployment
     * @return Accumulated rewards for subgraph
     */
    function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID)
        public
        override
        view
        returns (uint256)
    {
        Subgraph storage subgraph = subgraphs[_subgraphDeploymentID];

        uint256 newAccrued = getAccRewardsPerSignal().sub(subgraph.accRewardsPerSignalSnapshot);
        uint256 subgraphSignalledTokens = curation().getCurationPoolTokens(_subgraphDeploymentID);
        if (subgraphSignalledTokens == 0) {
            return 0;
        }

        uint256 newValue = newAccrued.mul(subgraphSignalledTokens).div(TOKEN_DECIMALS);
        return subgraph.accRewardsForSubgraph.add(newValue);
    }

    /**
     * @dev Gets the accumulated rewards per allocated token for the subgraph.
     * @param _subgraphDeploymentID Subgraph deployment
     * @return Accumulated rewards per allocated token for the subgraph
     * @return Accumulated rewards for subgraph
     */
    function getAccRewardsPerAllocatedToken(bytes32 _subgraphDeploymentID)
        public
        override
        view
        returns (uint256, uint256)
    {
        Subgraph storage subgraph = subgraphs[_subgraphDeploymentID];

        uint256 accRewardsForSubgraph = getAccRewardsForSubgraph(_subgraphDeploymentID);
        uint256 newAccrued = accRewardsForSubgraph.sub(subgraph.accRewardsForSubgraphSnapshot);

        uint256 subgraphAllocatedTokens = staking().getSubgraphAllocatedTokens(
            _subgraphDeploymentID
        );
        if (subgraphAllocatedTokens == 0) {
            return (0, accRewardsForSubgraph);
        }

        uint256 newValue = newAccrued.mul(TOKEN_DECIMALS).div(subgraphAllocatedTokens);
        return (subgraph.accRewardsPerAllocatedToken.add(newValue), accRewardsForSubgraph);
    }

    /**
     * @dev Updates the accumulated rewards per signal and save checkpoint block number.
     * Must be called before `issuanceRate` or `total signalled GRT` changes
     * Called from the Curation contract on mint() and burn()
     * @return Accumulated rewards per signal
     */
    function updateAccRewardsPerSignal() public override returns (uint256) {
        accRewardsPerSignal = getAccRewardsPerSignal();
        accRewardsPerSignalLastBlockUpdated = block.number;
        return accRewardsPerSignal;
    }

    /**
     * @dev Triggers an update of rewards for a subgraph.
     * Must be called before `signalled GRT` on a subgraph changes.
     * Note: Hook called from the Curation contract on mint() and burn()
     * @param _subgraphDeploymentID Subgraph deployment
     * @return Accumulated rewards for subgraph
     */
    function onSubgraphSignalUpdate(bytes32 _subgraphDeploymentID)
        external
        override
        returns (uint256)
    {
        // Called since `total signalled GRT` will change
        updateAccRewardsPerSignal();

        // Updates the accumulated rewards for a subgraph
        Subgraph storage subgraph = subgraphs[_subgraphDeploymentID];
        subgraph.accRewardsForSubgraph = getAccRewardsForSubgraph(_subgraphDeploymentID);
        subgraph.accRewardsPerSignalSnapshot = accRewardsPerSignal;
        return subgraph.accRewardsForSubgraph;
    }

    /**
     * @dev Triggers an update of rewards for a subgraph.
     * Must be called before allocation on a subgraph changes.
     * NOTE: Hook called from the Staking contract on allocate() and close()
     *
     * @param _subgraphDeploymentID Subgraph deployment
     * @return Accumulated rewards per allocated token for a subgraph
     */
    function onSubgraphAllocationUpdate(bytes32 _subgraphDeploymentID)
        public
        override
        returns (uint256)
    {
        Subgraph storage subgraph = subgraphs[_subgraphDeploymentID];
        (
            uint256 accRewardsPerAllocatedToken,
            uint256 accRewardsForSubgraph
        ) = getAccRewardsPerAllocatedToken(_subgraphDeploymentID);
        subgraph.accRewardsPerAllocatedToken = accRewardsPerAllocatedToken;
        subgraph.accRewardsForSubgraphSnapshot = accRewardsForSubgraph;
        return subgraph.accRewardsPerAllocatedToken;
    }

    /**
     * @dev Calculate current rewards for a given allocation on demand.
     * @param _allocationID Allocation
     * @return Rewards amount for an allocation
     */
    function getRewards(address _allocationID) external override view returns (uint256) {
        IStaking.Allocation memory alloc = staking().getAllocation(_allocationID);

        (uint256 accRewardsPerAllocatedToken, ) = getAccRewardsPerAllocatedToken(
            alloc.subgraphDeploymentID
        );
        return
            _calcRewards(
                alloc.tokens,
                alloc.accRewardsPerAllocatedToken,
                accRewardsPerAllocatedToken
            );
    }

    /**
     * @dev Calculate current rewards for a given allocation.
     * @param _tokens Tokens allocated
     * @param _startAccRewardsPerAllocatedToken Allocation start accumulated rewards
     * @param _endAccRewardsPerAllocatedToken Allocation end accumulated rewards
     * @return Rewards amount
     */
    function _calcRewards(
        uint256 _tokens,
        uint256 _startAccRewardsPerAllocatedToken,
        uint256 _endAccRewardsPerAllocatedToken
    ) private pure returns (uint256) {
        uint256 newAccrued = _endAccRewardsPerAllocatedToken.sub(_startAccRewardsPerAllocatedToken);
        return newAccrued.mul(_tokens).div(TOKEN_DECIMALS);
    }

    /**
     * @dev Pull rewards from the contract for a particular allocation.
     * This function can only be called by the Staking contract.
     * This function will mint the necessary tokens to reward based on the inflation calculation.
     * @param _allocationID Allocation
     * @return Assigned rewards amount
     */
    function takeRewards(address _allocationID) external override returns (uint256) {
        // Only Staking contract is authorized as caller
        IStaking staking = staking();
        require(msg.sender == address(staking), "Caller must be the staking contract");

        IGraphToken graphToken = graphToken();
        IStaking.Allocation memory alloc = staking.getAllocation(_allocationID);

        uint256 accRewardsPerAllocatedToken = onSubgraphAllocationUpdate(
            alloc.subgraphDeploymentID
        );

        // Do not do rewards on denied subgraph deployments ID
        if (isDenied(alloc.subgraphDeploymentID)) {
            emit RewardsDenied(alloc.indexer, _allocationID, alloc.closedAtEpoch);
            return 0;
        }

        // Calculate rewards accrued by this allocation
        uint256 rewards = _calcRewards(
            alloc.tokens,
            alloc.accRewardsPerAllocatedToken,
            accRewardsPerAllocatedToken
        );

        // Mint directly to staking contract for the reward amount
        // The staking contract will do bookkeeping of the reward and
        // assign in proportion to each stakeholder incentive
        graphToken.mint(address(staking), rewards);

        emit RewardsAssigned(alloc.indexer, _allocationID, alloc.closedAtEpoch, rewards);

        return rewards;
    }

    /**
     * @dev Raises x to the power of n with scaling factor of base.
     * Based on: https://github.com/makerdao/dss/blob/master/src/pot.sol#L81
     * @param x Base of the exponentiation
     * @param n Exponent
     * @param base Scaling factor
     * @return z Exponential of n with base x
     */
    function _pow(
        uint256 x,
        uint256 n,
        uint256 base
    ) private pure returns (uint256 z) {
        assembly {
            switch x
                case 0 {
                    switch n
                        case 0 {
                            z := base
                        }
                        default {
                            z := 0
                        }
                }
                default {
                    switch mod(n, 2)
                        case 0 {
                            z := base
                        }
                        default {
                            z := x
                        }
                    let half := div(base, 2) // for rounding.
                    for {
                        n := div(n, 2)
                    } n {
                        n := div(n, 2)
                    } {
                        let xx := mul(x, x)
                        if iszero(eq(div(xx, x), x)) {
                            revert(0, 0)
                        }
                        let xxRound := add(xx, half)
                        if lt(xxRound, xx) {
                            revert(0, 0)
                        }
                        x := div(xxRound, base)
                        if mod(n, 2) {
                            let zx := mul(z, x)
                            if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) {
                                revert(0, 0)
                            }
                            let zxRound := add(zx, half)
                            if lt(zxRound, zx) {
                                revert(0, 0)
                            }
                            z := div(zxRound, base)
                        }
                    }
                }
        }
    }
}

File 2 of 15 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

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

        return c;
    }

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

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

        return c;
    }

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

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

        return c;
    }

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

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

        return c;
    }

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

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

File 3 of 15 : GraphUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

import "./IGraphProxy.sol";

/**
 * @title Graph Upgradeable
 * @dev This contract is intended to be inherited from upgradeable contracts.
 */
contract GraphUpgradeable {
    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32
        internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Check if the caller is the proxy admin.
     */
    modifier onlyProxyAdmin(IGraphProxy _proxy) {
        require(msg.sender == _proxy.admin(), "Caller must be the proxy admin");
        _;
    }

    /**
     * @dev Check if the caller is the implementation.
     */
    modifier onlyImpl {
        require(msg.sender == _implementation(), "Caller must be the implementation");
        _;
    }

    /**
     * @dev Returns the current implementation.
     * @return impl Address of the current implementation
     */
    function _implementation() internal view returns (address impl) {
        bytes32 slot = IMPLEMENTATION_SLOT;
        assembly {
            impl := sload(slot)
        }
    }

    /**
     * @dev Accept to be an implementation of proxy.
     */
    function acceptProxy(IGraphProxy _proxy) external onlyProxyAdmin(_proxy) {
        _proxy.acceptUpgrade();
    }

    /**
     * @dev Accept to be an implementation of proxy and then call a function from the new
     * implementation as specified by `_data`, which should be an encoded function call. This is
     * useful to initialize new storage variables in the proxied contract.
     */
    function acceptProxyAndCall(IGraphProxy _proxy, bytes calldata _data)
        external
        onlyProxyAdmin(_proxy)
    {
        _proxy.acceptUpgradeAndCall(_data);
    }
}

File 4 of 15 : RewardsManagerStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

import "./IRewardsManager.sol";
import "../governance/Managed.sol";

contract RewardsManagerV1Storage is Managed {
    // -- State --

    uint256 public issuanceRate;
    uint256 public accRewardsPerSignal;
    uint256 public accRewardsPerSignalLastBlockUpdated;

    // Address of role allowed to deny rewards on subgraphs
    address public subgraphAvailabilityOracle;

    // Subgraph related rewards: subgraph deployment ID => subgraph rewards
    mapping(bytes32 => IRewardsManager.Subgraph) public subgraphs;

    // Subgraph denylist : subgraph deployment ID => block when added or zero (if not denied)
    mapping(bytes32 => uint256) public denylist;
}

File 5 of 15 : IRewardsManager.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface IRewardsManager {
    /**
     * @dev Stores accumulated rewards and snapshots related to a particular SubgraphDeployment.
     */
    struct Subgraph {
        uint256 accRewardsForSubgraph;
        uint256 accRewardsForSubgraphSnapshot;
        uint256 accRewardsPerSignalSnapshot;
        uint256 accRewardsPerAllocatedToken;
    }

    // -- Params --

    function setIssuanceRate(uint256 _issuanceRate) external;

    // -- Denylist --

    function setSubgraphAvailabilityOracle(address _subgraphAvailabilityOracle) external;

    function setDenied(bytes32 _subgraphDeploymentID, bool _deny) external;

    function setDeniedMany(bytes32[] calldata _subgraphDeploymentID, bool[] calldata _deny)
        external;

    function isDenied(bytes32 _subgraphDeploymentID) external view returns (bool);

    // -- Getters --

    function getNewRewardsPerSignal() external view returns (uint256);

    function getAccRewardsPerSignal() external view returns (uint256);

    function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID)
        external
        view
        returns (uint256);

    function getAccRewardsPerAllocatedToken(bytes32 _subgraphDeploymentID)
        external
        view
        returns (uint256, uint256);

    function getRewards(address _allocationID) external view returns (uint256);

    // -- Updates --

    function updateAccRewardsPerSignal() external returns (uint256);

    function takeRewards(address _allocationID) external returns (uint256);

    // -- Hooks --

    function onSubgraphSignalUpdate(bytes32 _subgraphDeploymentID) external returns (uint256);

    function onSubgraphAllocationUpdate(bytes32 _subgraphDeploymentID) external returns (uint256);
}

File 6 of 15 : IGraphProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface IGraphProxy {
    function admin() external returns (address);

    function setAdmin(address _newAdmin) external;

    function implementation() external returns (address);

    function pendingImplementation() external returns (address);

    function upgradeTo(address _newImplementation) external;

    function acceptUpgrade() external;

    function acceptUpgradeAndCall(bytes calldata data) external;
}

File 7 of 15 : Managed.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

import "./IManaged.sol";
import "./IController.sol";
import "../curation/ICuration.sol";
import "../epochs/IEpochManager.sol";
import "../rewards/IRewardsManager.sol";
import "../staking/IStaking.sol";
import "../token/IGraphToken.sol";

/**
 * @title Graph Managed contract
 * @dev The Managed contract provides an interface for contracts to interact with the Controller
 * Inspired by Livepeer:
 * https://github.com/livepeer/protocol/blob/streamflow/contracts/Controller.sol
 */
contract Managed {
    // Controller that contract is registered with
    IController public controller;
    mapping(bytes32 => address) public addressCache;
    uint256[10] private __gap;

    event ParameterUpdated(string param);
    event SetController(address controller);

    function _notPartialPaused() internal view {
        require(!controller.paused(), "Paused");
        require(!controller.partialPaused(), "Partial-paused");
    }

    function _notPaused() internal view {
        require(!controller.paused(), "Paused");
    }

    function _onlyGovernor() internal view {
        require(msg.sender == controller.getGovernor(), "Caller must be Controller governor");
    }

    modifier notPartialPaused {
        _notPartialPaused();
        _;
    }

    modifier notPaused {
        _notPaused();
        _;
    }

    // Check if sender is controller
    modifier onlyController() {
        require(msg.sender == address(controller), "Caller must be Controller");
        _;
    }

    modifier onlyGovernor() {
        _onlyGovernor();
        _;
    }

    /**
     * @dev Initialize the controller
     */
    function _initialize(address _controller) internal {
        _setController(_controller);
    }

    /**
     * @notice Set Controller. Only callable by current controller
     * @param _controller Controller contract address
     */
    function setController(address _controller) external onlyController {
        _setController(_controller);
    }

    /**
     * @dev Set controller.
     * @param _controller Controller contract address
     */
    function _setController(address _controller) internal {
        require(_controller != address(0), "Controller must be set");
        controller = IController(_controller);
        emit SetController(_controller);
    }

    /**
     * @dev Return Curation interface
     * @return Curation contract registered with Controller
     */
    function curation() internal view returns (ICuration) {
        return ICuration(controller.getContractProxy(keccak256("Curation")));
    }

    /**
     * @dev Return EpochManager interface
     * @return Epoch manager contract registered with Controller
     */
    function epochManager() internal view returns (IEpochManager) {
        return IEpochManager(controller.getContractProxy(keccak256("EpochManager")));
    }

    /**
     * @dev Return RewardsManager interface
     * @return Rewards manager contract registered with Controller
     */
    function rewardsManager() internal view returns (IRewardsManager) {
        return IRewardsManager(controller.getContractProxy(keccak256("RewardsManager")));
    }

    /**
     * @dev Return Staking interface
     * @return Staking contract registered with Controller
     */
    function staking() internal view returns (IStaking) {
        return IStaking(controller.getContractProxy(keccak256("Staking")));
    }

    /**
     * @dev Return GraphToken interface
     * @return Graph token contract registered with Controller
     */
    function graphToken() internal view returns (IGraphToken) {
        return IGraphToken(controller.getContractProxy(keccak256("GraphToken")));
    }
}

File 8 of 15 : IManaged.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface IManaged {
    function setController(address _controller) external;
}

File 9 of 15 : IController.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.12 <0.8.0;

interface IController {
    function getGovernor() external view returns (address);

    // -- Registry --

    function setContractProxy(bytes32 _id, address _contractAddress) external;

    function unsetContractProxy(bytes32 _id) external;

    function updateController(bytes32 _id, address _controller) external;

    function getContractProxy(bytes32 _id) external view returns (address);

    // -- Pausing --

    function setPartialPaused(bool _partialPaused) external;

    function setPaused(bool _paused) external;

    function setPauseGuardian(address _newPauseGuardian) external;

    function paused() external view returns (bool);

    function partialPaused() external view returns (bool);
}

File 10 of 15 : ICuration.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

import "./IGraphCurationToken.sol";

interface ICuration {
    // -- Pool --

    struct CurationPool {
        uint256 tokens; // GRT Tokens stored as reserves for the subgraph deployment
        uint32 reserveRatio; // Ratio for the bonding curve
        IGraphCurationToken gcs; // Curation token contract for this curation pool
    }

    // -- Configuration --

    function setDefaultReserveRatio(uint32 _defaultReserveRatio) external;

    function setMinimumCurationDeposit(uint256 _minimumCurationDeposit) external;

    function setCurationTaxPercentage(uint32 _percentage) external;

    // -- Curation --

    function mint(
        bytes32 _subgraphDeploymentID,
        uint256 _tokensIn,
        uint256 _signalOutMin
    ) external returns (uint256, uint256);

    function burn(
        bytes32 _subgraphDeploymentID,
        uint256 _signalIn,
        uint256 _tokensOutMin
    ) external returns (uint256);

    function collect(bytes32 _subgraphDeploymentID, uint256 _tokens) external;

    // -- Getters --

    function isCurated(bytes32 _subgraphDeploymentID) external view returns (bool);

    function getCuratorSignal(address _curator, bytes32 _subgraphDeploymentID)
        external
        view
        returns (uint256);

    function getCurationPoolSignal(bytes32 _subgraphDeploymentID) external view returns (uint256);

    function getCurationPoolTokens(bytes32 _subgraphDeploymentID) external view returns (uint256);

    function tokensToSignal(bytes32 _subgraphDeploymentID, uint256 _tokensIn)
        external
        view
        returns (uint256, uint256);

    function signalToTokens(bytes32 _subgraphDeploymentID, uint256 _signalIn)
        external
        view
        returns (uint256);

    function curationTaxPercentage() external view returns (uint32);
}

File 11 of 15 : IEpochManager.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface IEpochManager {
    // -- Configuration --

    function setEpochLength(uint256 _epochLength) external;

    // -- Epochs

    function runEpoch() external;

    // -- Getters --

    function isCurrentEpochRun() external view returns (bool);

    function blockNum() external view returns (uint256);

    function blockHash(uint256 _block) external view returns (bytes32);

    function currentEpoch() external view returns (uint256);

    function currentEpochBlock() external view returns (uint256);

    function currentEpochBlockSinceStart() external view returns (uint256);

    function epochsSince(uint256 _epoch) external view returns (uint256);

    function epochsSinceUpdate() external view returns (uint256);
}

File 12 of 15 : IStaking.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.12 <0.8.0;
pragma experimental ABIEncoderV2;

interface IStaking {
    // -- Allocation Data --

    /**
     * @dev Possible states an allocation can be
     * States:
     * - Null = indexer == address(0)
     * - Active = not Null && tokens > 0
     * - Closed = Active && closedAtEpoch != 0
     * - Finalized = Closed && closedAtEpoch + channelDisputeEpochs > now()
     * - Claimed = not Null && tokens == 0
     */
    enum AllocationState { Null, Active, Closed, Finalized, Claimed }

    /**
     * @dev Allocate GRT tokens for the purpose of serving queries of a subgraph deployment
     * An allocation is created in the allocate() function and consumed in claim()
     */
    struct Allocation {
        address indexer;
        bytes32 subgraphDeploymentID;
        uint256 tokens; // Tokens allocated to a SubgraphDeployment
        uint256 createdAtEpoch; // Epoch when it was created
        uint256 closedAtEpoch; // Epoch when it was closed
        uint256 collectedFees; // Collected fees for the allocation
        uint256 effectiveAllocation; // Effective allocation when closed
        uint256 accRewardsPerAllocatedToken; // Snapshot used for reward calc
    }

    /**
     * @dev Represents a request to close an allocation with a specific proof of indexing.
     * This is passed when calling closeAllocationMany to define the closing parameters for
     * each allocation.
     */
    struct CloseAllocationRequest {
        address allocationID;
        bytes32 poi;
    }

    // -- Delegation Data --

    /**
     * @dev Delegation pool information. One per indexer.
     */
    struct DelegationPool {
        uint32 cooldownBlocks; // Blocks to wait before updating parameters
        uint32 indexingRewardCut; // in PPM
        uint32 queryFeeCut; // in PPM
        uint256 updatedAtBlock; // Block when the pool was last updated
        uint256 tokens; // Total tokens as pool reserves
        uint256 shares; // Total shares minted in the pool
        mapping(address => Delegation) delegators; // Mapping of delegator => Delegation
    }

    /**
     * @dev Individual delegation data of a delegator in a pool.
     */
    struct Delegation {
        uint256 shares; // Shares owned by a delegator in the pool
        uint256 tokensLocked; // Tokens locked for undelegation
        uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn
    }

    // -- Configuration --

    function setMinimumIndexerStake(uint256 _minimumIndexerStake) external;

    function setThawingPeriod(uint32 _thawingPeriod) external;

    function setCurationPercentage(uint32 _percentage) external;

    function setProtocolPercentage(uint32 _percentage) external;

    function setChannelDisputeEpochs(uint32 _channelDisputeEpochs) external;

    function setMaxAllocationEpochs(uint32 _maxAllocationEpochs) external;

    function setRebateRatio(uint32 _alphaNumerator, uint32 _alphaDenominator) external;

    function setDelegationRatio(uint32 _delegationRatio) external;

    function setDelegationParameters(
        uint32 _indexingRewardCut,
        uint32 _queryFeeCut,
        uint32 _cooldownBlocks
    ) external;

    function setDelegationParametersCooldown(uint32 _blocks) external;

    function setDelegationUnbondingPeriod(uint32 _delegationUnbondingPeriod) external;

    function setDelegationTaxPercentage(uint32 _percentage) external;

    function setSlasher(address _slasher, bool _allowed) external;

    function setAssetHolder(address _assetHolder, bool _allowed) external;

    // -- Operation --

    function setOperator(address _operator, bool _allowed) external;

    function isOperator(address _operator, address _indexer) external view returns (bool);

    // -- Staking --

    function stake(uint256 _tokens) external;

    function stakeTo(address _indexer, uint256 _tokens) external;

    function unstake(uint256 _tokens) external;

    function slash(
        address _indexer,
        uint256 _tokens,
        uint256 _reward,
        address _beneficiary
    ) external;

    function withdraw() external;

    // -- Delegation --

    function delegate(address _indexer, uint256 _tokens) external returns (uint256);

    function undelegate(address _indexer, uint256 _shares) external returns (uint256);

    function withdrawDelegated(address _indexer, address _newIndexer) external returns (uint256);

    // -- Channel management and allocations --

    function allocate(
        bytes32 _subgraphDeploymentID,
        uint256 _tokens,
        address _allocationID,
        bytes32 _metadata,
        bytes calldata _proof
    ) external;

    function allocateFrom(
        address _indexer,
        bytes32 _subgraphDeploymentID,
        uint256 _tokens,
        address _allocationID,
        bytes32 _metadata,
        bytes calldata _proof
    ) external;

    function closeAllocation(address _allocationID, bytes32 _poi) external;

    function closeAllocationMany(CloseAllocationRequest[] calldata _requests) external;

    function closeAndAllocate(
        address _oldAllocationID,
        bytes32 _poi,
        address _indexer,
        bytes32 _subgraphDeploymentID,
        uint256 _tokens,
        address _allocationID,
        bytes32 _metadata,
        bytes calldata _proof
    ) external;

    function collect(uint256 _tokens, address _allocationID) external;

    function claim(address _allocationID, bool _restake) external;

    function claimMany(address[] calldata _allocationID, bool _restake) external;

    // -- Getters and calculations --

    function hasStake(address _indexer) external view returns (bool);

    function getIndexerStakedTokens(address _indexer) external view returns (uint256);

    function getIndexerCapacity(address _indexer) external view returns (uint256);

    function getAllocation(address _allocationID) external view returns (Allocation memory);

    function getAllocationState(address _allocationID) external view returns (AllocationState);

    function isAllocation(address _allocationID) external view returns (bool);

    function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentID)
        external
        view
        returns (uint256);

    function getDelegation(address _indexer, address _delegator)
        external
        view
        returns (Delegation memory);

    function isDelegator(address _indexer, address _delegator) external view returns (bool);
}

File 13 of 15 : IGraphToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IGraphToken is IERC20 {
    // -- Mint and Burn --

    function burn(uint256 amount) external;

    function mint(address _to, uint256 _amount) external;

    // -- Mint Admin --

    function addMinter(address _account) external;

    function removeMinter(address _account) external;

    function renounceMinter() external;

    function isMinter(address _account) external view returns (bool);

    // -- Permit --

    function permit(
        address _owner,
        address _spender,
        uint256 _value,
        uint256 _deadline,
        uint8 _v,
        bytes32 _r,
        bytes32 _s
    ) external;
}

File 14 of 15 : IGraphCurationToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IGraphCurationToken is IERC20 {
    function burnFrom(address _account, uint256 _amount) external;

    function mint(address _to, uint256 _amount) external;
}

File 15 of 15 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

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

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

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

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"param","type":"string"}],"name":"ParameterUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"indexer","type":"address"},{"indexed":true,"internalType":"address","name":"allocationID","type":"address"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsAssigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"indexer","type":"address"},{"indexed":true,"internalType":"address","name":"allocationID","type":"address"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"RewardsDenied","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"subgraphDeploymentID","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"sinceBlock","type":"uint256"}],"name":"RewardsDenylistUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"controller","type":"address"}],"name":"SetController","type":"event"},{"inputs":[],"name":"accRewardsPerSignal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accRewardsPerSignalLastBlockUpdated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IGraphProxy","name":"_proxy","type":"address"}],"name":"acceptProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IGraphProxy","name":"_proxy","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"acceptProxyAndCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"addressCache","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"contract IController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"denylist","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_subgraphDeploymentID","type":"bytes32"}],"name":"getAccRewardsForSubgraph","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_subgraphDeploymentID","type":"bytes32"}],"name":"getAccRewardsPerAllocatedToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAccRewardsPerSignal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNewRewardsPerSignal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_allocationID","type":"address"}],"name":"getRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_controller","type":"address"},{"internalType":"uint256","name":"_issuanceRate","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_subgraphDeploymentID","type":"bytes32"}],"name":"isDenied","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"issuanceRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_subgraphDeploymentID","type":"bytes32"}],"name":"onSubgraphAllocationUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_subgraphDeploymentID","type":"bytes32"}],"name":"onSubgraphSignalUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_controller","type":"address"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_subgraphDeploymentID","type":"bytes32"},{"internalType":"bool","name":"_deny","type":"bool"}],"name":"setDenied","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_subgraphDeploymentID","type":"bytes32[]"},{"internalType":"bool[]","name":"_deny","type":"bool[]"}],"name":"setDeniedMany","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_issuanceRate","type":"uint256"}],"name":"setIssuanceRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_subgraphAvailabilityOracle","type":"address"}],"name":"setSubgraphAvailabilityOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subgraphAvailabilityOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"subgraphs","outputs":[{"internalType":"uint256","name":"accRewardsForSubgraph","type":"uint256"},{"internalType":"uint256","name":"accRewardsForSubgraphSnapshot","type":"uint256"},{"internalType":"uint256","name":"accRewardsPerSignalSnapshot","type":"uint256"},{"internalType":"uint256","name":"accRewardsPerAllocatedToken","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_allocationID","type":"address"}],"name":"takeRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateAccRewardsPerSignal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50611c2d806100206000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639ce7abe5116100de578063dc675a6511610097578063e820e28411610071578063e820e2841461032b578063eeac3e0e1461034b578063f77c47911461035e578063fc24ffdf146103665761018e565b8063dc675a6514610308578063e242cf1e1461031b578063e284f848146103235761018e565b80639ce7abe5146102ac578063a2594d82146102bf578063a8cc0ee2146102d2578063c7d1117d146102da578063cd6dc687146102e2578063db750926146102f55761018e565b80633c9ae2ba1161014b578063702a280e11610125578063702a280e1461025d57806379ee54f71461027e5780639006ce8b1461029157806392eefe9b146102995761018e565b80633c9ae2ba1461021f5780634986594f146102275780635c6cbd591461024a5761018e565b806305bb8c6b146101935780630903c094146101b15780631324a506146101c657806316a84ab2146101d95780631d1c2fec146101f95780631debaded1461020c575b600080fd5b61019b610379565b6040516101a891906119c1565b60405180910390f35b6101c46101bf36600461178c565b610388565b005b6101c46101d436600461186e565b6103e4565b6101ec6101e7366004611856565b610425565b6040516101a891906119f9565b6101ec610207366004611856565b610437565b6101c461021a3660046117d3565b610470565b6101ec61050f565b61023a610235366004611856565b610515565b6040516101a89493929190611b63565b6101ec610258366004611856565b61053c565b61027061026b366004611856565b610634565b6040516101a8929190611b55565b6101ec61028c36600461178c565b610740565b6101ec6107fd565b6101c46102a736600461178c565b610803565b6101c46102ba366004611899565b61086e565b6101c46102cd36600461178c565b6109c4565b6101ec610adf565b6101ec610afb565b6101c46102f03660046117a8565b610b13565b6101ec61030336600461178c565b610b7c565b61019b610316366004611856565b610d9e565b6101ec610db9565b6101ec610dbf565b61033e610339366004611856565b610f80565b6040516101a891906119ee565b6101ec610359366004611856565b610f94565b61019b610fc6565b6101c4610374366004611856565b610fd5565b600f546001600160a01b031681565b610390610fe6565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c906103d990611a02565b60405180910390a150565b600f546001600160a01b031633146104175760405162461bcd60e51b815260040161040e90611a7c565b60405180910390fd5b61042182826110a6565b5050565b60116020526000908152604090205481565b6000610441610afb565b5060008281526010602052604090206104598361053c565b808255600d5460029092019190915590505b919050565b600f546001600160a01b0316331461049a5760405162461bcd60e51b815260040161040e90611a7c565b8281146104b95760405162461bcd60e51b815260040161040e90611b34565b60005b83811015610508576105008585838181106104d357fe5b905060200201358484848181106104e657fe5b90506020020160208101906104fb919061183c565b6110a6565b6001016104bc565b5050505050565b600c5481565b60106020526000908152604090208054600182015460028301546003909301549192909184565b6000818152601060205260408120600281015482906105639061055d610adf565b90611109565b9050600061056f611154565b6001600160a01b03166346e855da866040518263ffffffff1660e01b815260040161059a91906119f9565b60206040518083038186803b1580156105b257600080fd5b505afa1580156105c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ea91906119a9565b9050806105fd576000935050505061046b565b600061061b670de0b6b3a764000061061585856111f1565b9061124a565b845490915061062a908261128c565b9695505050505050565b600081815260106020526040812081908161064e8561053c565b9050600061066983600101548361110990919063ffffffff16565b905060006106756112e6565b6001600160a01b031663e2e1e8e9886040518263ffffffff1660e01b81526004016106a091906119f9565b60206040518083038186803b1580156106b857600080fd5b505afa1580156106cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f091906119a9565b90508061070757600083955095505050505061073b565b600061071f8261061585670de0b6b3a76400006111f1565b6003860154909150610731908261128c565b9650929450505050505b915091565b600061074a6116d7565b6107526112e6565b6001600160a01b0316630e022923846040518263ffffffff1660e01b815260040161077d91906119c1565b6101006040518083038186803b15801561079657600080fd5b505afa1580156107aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ce9190611919565b905060006107df8260200151610634565b5090506107f582604001518360e0015183611352565b949350505050565b600e5481565b6000546001600160a01b03163314610862576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b61086b81611380565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156108aa57600080fd5b505af11580156108be573d6000803e3d6000fd5b505050506040513d60208110156108d457600080fd5b50516001600160a01b03163314610932576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156109a657600080fd5b505af11580156109ba573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610a0057600080fd5b505af1158015610a14573d6000803e3d6000fd5b505050506040513d6020811015610a2a57600080fd5b50516001600160a01b03163314610a88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ac357600080fd5b505af1158015610ad7573d6000803e3d6000fd5b505050505050565b6000610af5610aec610dbf565b600d549061128c565b90505b90565b6000610b05610adf565b600d81905543600e55905090565b610b1b611428565b6001600160a01b0316336001600160a01b031614610b6a5760405162461bcd60e51b8152600401808060200182810382526021815260200180611bd76021913960400191505060405180910390fd5b610b7382610862565b6104218161144d565b600080610b876112e6565b9050336001600160a01b03821614610bb15760405162461bcd60e51b815260040161040e90611af1565b6000610bbb6114b1565b9050610bc56116d7565b604051630e02292360e01b81526001600160a01b03841690630e02292390610bf19088906004016119c1565b6101006040518083038186803b158015610c0a57600080fd5b505afa158015610c1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c429190611919565b90506000610c538260200151610f94565b9050610c628260200151610f80565b15610cc757856001600160a01b031682600001516001600160a01b03167f07b6d8dafdf1323cc892f303125d1308c0edc07b15b14b6de6dcb4a5eea818fa8460800151604051610cb291906119f9565b60405180910390a3600094505050505061046b565b6000610cdc83604001518460e0015184611352565b6040516340c10f1960e01b81529091506001600160a01b038516906340c10f1990610d0d90889085906004016119d5565b600060405180830381600087803b158015610d2757600080fd5b505af1158015610d3b573d6000803e3d6000fd5b50505050866001600160a01b031683600001516001600160a01b03167f315d9cdbc182c9118c140c78a121ebb9f24bf73f841339a8a41cdc3586c34e18856080015184604051610d8c929190611b55565b60405180910390a39695505050505050565b6001602052600090815260409020546001600160a01b031681565b600d5481565b600080610dd7600e544361110990919063ffffffff16565b905080610de8576000915050610af8565b670de0b6b3a7640000600c5411610e03576000915050610af8565b6000610e0d6114b1565b90506000816001600160a01b03166370a08231610e28611154565b6040518263ffffffff1660e01b8152600401610e4491906119c1565b60206040518083038186803b158015610e5c57600080fd5b505afa158015610e70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9491906119a9565b905080610ea75760009350505050610af8565b6000600c5490506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ee957600080fd5b505afa158015610efd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2191906119a9565b90506000610f4e670de0b6b3a7640000610615610f47868a670de0b6b3a764000061151d565b85906111f1565b90506000610f5c8284611109565b9050610f748561061583670de0b6b3a76400006111f1565b97505050505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180610fad85610634565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b610fdd610fe6565b61086b8161144d565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561103257600080fd5b505afa158015611046573d6000803e3d6000fd5b505050506040513d602081101561105c57600080fd5b50516001600160a01b031633146110a45760405162461bcd60e51b8152600401808060200182810382526022815260200180611bb56022913960400191505060405180910390fd5b565b6000816110b45760006110b6565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a906110fc9084906119f9565b60405180910390a2505050565b600061114b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506115db565b90505b92915050565b6000805460408051637bb20d2f60e11b81527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f600482015290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156111c057600080fd5b505afa1580156111d4573d6000803e3d6000fd5b505050506040513d60208110156111ea57600080fd5b5051905090565b6000826112005750600061114e565b8282028284828161120d57fe5b041461114b5760405162461bcd60e51b8152600401808060200182810382526021815260200180611b946021913960400191505060405180910390fd5b600061114b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611672565b60008282018381101561114b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000805460408051637bb20d2f60e11b81527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034600482015290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156111c057600080fd5b60008061135f8385611109565b9050611377670de0b6b3a764000061061583886111f1565b95945050505050565b6001600160a01b0381166113d4576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b670de0b6b3a76400008110156114755760405162461bcd60e51b815260040161040e90611a39565b61147d610afb565b50600c8190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c906103d990611acb565b6000805460408051637bb20d2f60e11b81527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247600482015290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156111c057600080fd5b60008380156115bd576001841680156115385785925061153c565b8392505b50600283046002850494505b84156115b757858602868782041461155f57600080fd5b8181018181101561156f57600080fd5b85900496505060018516156115ac57858302838782041415871515161561159557600080fd5b818101818110156115a557600080fd5b8590049350505b600285049450611548565b506115d3565b8380156115cd57600092506115d1565b8392505b505b509392505050565b6000818484111561166a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561162f578181015183820152602001611617565b50505050905090810190601f16801561165c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836116c15760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561162f578181015183820152602001611617565b5060008385816116cd57fe5b0495945050505050565b60405180610100016040528060006001600160a01b03168152602001600080191681526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b805161046b81611b7e565b60008083601f840112611744578182fd5b50813567ffffffffffffffff81111561175b578182fd5b602083019150836020808302850101111561177557600080fd5b9250929050565b8035801515811461046b57600080fd5b60006020828403121561179d578081fd5b813561114b81611b7e565b600080604083850312156117ba578081fd5b82356117c581611b7e565b946020939093013593505050565b600080600080604085870312156117e8578182fd5b843567ffffffffffffffff808211156117ff578384fd5b61180b88838901611733565b90965094506020870135915080821115611823578384fd5b5061183087828801611733565b95989497509550505050565b60006020828403121561184d578081fd5b61114b8261177c565b600060208284031215611867578081fd5b5035919050565b60008060408385031215611880578182fd5b823591506118906020840161177c565b90509250929050565b6000806000604084860312156118ad578283fd5b83356118b881611b7e565b9250602084013567ffffffffffffffff808211156118d4578384fd5b818601915086601f8301126118e7578384fd5b8135818111156118f5578485fd5b876020828501011115611906578485fd5b6020830194508093505050509250925092565b600061010080838503121561192c578182fd5b6040519081019067ffffffffffffffff8211818310171561194957fe5b8160405261195684611728565b81526020840151602082015260408401516040820152606084015160608201526080840151608082015260a084015160a082015260c084015160c082015260e084015160e0820152809250505092915050565b6000602082840312156119ba578081fd5b5051919050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b60208082526023908201527f49737375616e6365207261746520756e646572206d696e696d756d20616c6c6f6040820152621dd95960ea1b606082015260800190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252600c908201526b69737375616e63655261746560a01b604082015260600190565b60208082526023908201527f43616c6c6572206d75737420626520746865207374616b696e6720636f6e74726040820152621858dd60ea1b606082015260800190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461086b57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206d75737420626520436f6e74726f6c6c657220676f7665726e6f7243616c6c6572206d7573742062652074686520696d706c656d656e746174696f6ea2646970667358221220a002cd24dc390f17b6944d68d32e345ae62f4f424f5cff28d60a4cf57180d93864736f6c63430007040033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061018e5760003560e01c80639ce7abe5116100de578063dc675a6511610097578063e820e28411610071578063e820e2841461032b578063eeac3e0e1461034b578063f77c47911461035e578063fc24ffdf146103665761018e565b8063dc675a6514610308578063e242cf1e1461031b578063e284f848146103235761018e565b80639ce7abe5146102ac578063a2594d82146102bf578063a8cc0ee2146102d2578063c7d1117d146102da578063cd6dc687146102e2578063db750926146102f55761018e565b80633c9ae2ba1161014b578063702a280e11610125578063702a280e1461025d57806379ee54f71461027e5780639006ce8b1461029157806392eefe9b146102995761018e565b80633c9ae2ba1461021f5780634986594f146102275780635c6cbd591461024a5761018e565b806305bb8c6b146101935780630903c094146101b15780631324a506146101c657806316a84ab2146101d95780631d1c2fec146101f95780631debaded1461020c575b600080fd5b61019b610379565b6040516101a891906119c1565b60405180910390f35b6101c46101bf36600461178c565b610388565b005b6101c46101d436600461186e565b6103e4565b6101ec6101e7366004611856565b610425565b6040516101a891906119f9565b6101ec610207366004611856565b610437565b6101c461021a3660046117d3565b610470565b6101ec61050f565b61023a610235366004611856565b610515565b6040516101a89493929190611b63565b6101ec610258366004611856565b61053c565b61027061026b366004611856565b610634565b6040516101a8929190611b55565b6101ec61028c36600461178c565b610740565b6101ec6107fd565b6101c46102a736600461178c565b610803565b6101c46102ba366004611899565b61086e565b6101c46102cd36600461178c565b6109c4565b6101ec610adf565b6101ec610afb565b6101c46102f03660046117a8565b610b13565b6101ec61030336600461178c565b610b7c565b61019b610316366004611856565b610d9e565b6101ec610db9565b6101ec610dbf565b61033e610339366004611856565b610f80565b6040516101a891906119ee565b6101ec610359366004611856565b610f94565b61019b610fc6565b6101c4610374366004611856565b610fd5565b600f546001600160a01b031681565b610390610fe6565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c906103d990611a02565b60405180910390a150565b600f546001600160a01b031633146104175760405162461bcd60e51b815260040161040e90611a7c565b60405180910390fd5b61042182826110a6565b5050565b60116020526000908152604090205481565b6000610441610afb565b5060008281526010602052604090206104598361053c565b808255600d5460029092019190915590505b919050565b600f546001600160a01b0316331461049a5760405162461bcd60e51b815260040161040e90611a7c565b8281146104b95760405162461bcd60e51b815260040161040e90611b34565b60005b83811015610508576105008585838181106104d357fe5b905060200201358484848181106104e657fe5b90506020020160208101906104fb919061183c565b6110a6565b6001016104bc565b5050505050565b600c5481565b60106020526000908152604090208054600182015460028301546003909301549192909184565b6000818152601060205260408120600281015482906105639061055d610adf565b90611109565b9050600061056f611154565b6001600160a01b03166346e855da866040518263ffffffff1660e01b815260040161059a91906119f9565b60206040518083038186803b1580156105b257600080fd5b505afa1580156105c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ea91906119a9565b9050806105fd576000935050505061046b565b600061061b670de0b6b3a764000061061585856111f1565b9061124a565b845490915061062a908261128c565b9695505050505050565b600081815260106020526040812081908161064e8561053c565b9050600061066983600101548361110990919063ffffffff16565b905060006106756112e6565b6001600160a01b031663e2e1e8e9886040518263ffffffff1660e01b81526004016106a091906119f9565b60206040518083038186803b1580156106b857600080fd5b505afa1580156106cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f091906119a9565b90508061070757600083955095505050505061073b565b600061071f8261061585670de0b6b3a76400006111f1565b6003860154909150610731908261128c565b9650929450505050505b915091565b600061074a6116d7565b6107526112e6565b6001600160a01b0316630e022923846040518263ffffffff1660e01b815260040161077d91906119c1565b6101006040518083038186803b15801561079657600080fd5b505afa1580156107aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ce9190611919565b905060006107df8260200151610634565b5090506107f582604001518360e0015183611352565b949350505050565b600e5481565b6000546001600160a01b03163314610862576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b61086b81611380565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156108aa57600080fd5b505af11580156108be573d6000803e3d6000fd5b505050506040513d60208110156108d457600080fd5b50516001600160a01b03163314610932576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156109a657600080fd5b505af11580156109ba573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610a0057600080fd5b505af1158015610a14573d6000803e3d6000fd5b505050506040513d6020811015610a2a57600080fd5b50516001600160a01b03163314610a88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ac357600080fd5b505af1158015610ad7573d6000803e3d6000fd5b505050505050565b6000610af5610aec610dbf565b600d549061128c565b90505b90565b6000610b05610adf565b600d81905543600e55905090565b610b1b611428565b6001600160a01b0316336001600160a01b031614610b6a5760405162461bcd60e51b8152600401808060200182810382526021815260200180611bd76021913960400191505060405180910390fd5b610b7382610862565b6104218161144d565b600080610b876112e6565b9050336001600160a01b03821614610bb15760405162461bcd60e51b815260040161040e90611af1565b6000610bbb6114b1565b9050610bc56116d7565b604051630e02292360e01b81526001600160a01b03841690630e02292390610bf19088906004016119c1565b6101006040518083038186803b158015610c0a57600080fd5b505afa158015610c1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c429190611919565b90506000610c538260200151610f94565b9050610c628260200151610f80565b15610cc757856001600160a01b031682600001516001600160a01b03167f07b6d8dafdf1323cc892f303125d1308c0edc07b15b14b6de6dcb4a5eea818fa8460800151604051610cb291906119f9565b60405180910390a3600094505050505061046b565b6000610cdc83604001518460e0015184611352565b6040516340c10f1960e01b81529091506001600160a01b038516906340c10f1990610d0d90889085906004016119d5565b600060405180830381600087803b158015610d2757600080fd5b505af1158015610d3b573d6000803e3d6000fd5b50505050866001600160a01b031683600001516001600160a01b03167f315d9cdbc182c9118c140c78a121ebb9f24bf73f841339a8a41cdc3586c34e18856080015184604051610d8c929190611b55565b60405180910390a39695505050505050565b6001602052600090815260409020546001600160a01b031681565b600d5481565b600080610dd7600e544361110990919063ffffffff16565b905080610de8576000915050610af8565b670de0b6b3a7640000600c5411610e03576000915050610af8565b6000610e0d6114b1565b90506000816001600160a01b03166370a08231610e28611154565b6040518263ffffffff1660e01b8152600401610e4491906119c1565b60206040518083038186803b158015610e5c57600080fd5b505afa158015610e70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9491906119a9565b905080610ea75760009350505050610af8565b6000600c5490506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ee957600080fd5b505afa158015610efd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2191906119a9565b90506000610f4e670de0b6b3a7640000610615610f47868a670de0b6b3a764000061151d565b85906111f1565b90506000610f5c8284611109565b9050610f748561061583670de0b6b3a76400006111f1565b97505050505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180610fad85610634565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b610fdd610fe6565b61086b8161144d565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561103257600080fd5b505afa158015611046573d6000803e3d6000fd5b505050506040513d602081101561105c57600080fd5b50516001600160a01b031633146110a45760405162461bcd60e51b8152600401808060200182810382526022815260200180611bb56022913960400191505060405180910390fd5b565b6000816110b45760006110b6565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a906110fc9084906119f9565b60405180910390a2505050565b600061114b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506115db565b90505b92915050565b6000805460408051637bb20d2f60e11b81527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f600482015290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156111c057600080fd5b505afa1580156111d4573d6000803e3d6000fd5b505050506040513d60208110156111ea57600080fd5b5051905090565b6000826112005750600061114e565b8282028284828161120d57fe5b041461114b5760405162461bcd60e51b8152600401808060200182810382526021815260200180611b946021913960400191505060405180910390fd5b600061114b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611672565b60008282018381101561114b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000805460408051637bb20d2f60e11b81527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034600482015290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156111c057600080fd5b60008061135f8385611109565b9050611377670de0b6b3a764000061061583886111f1565b95945050505050565b6001600160a01b0381166113d4576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b670de0b6b3a76400008110156114755760405162461bcd60e51b815260040161040e90611a39565b61147d610afb565b50600c8190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c906103d990611acb565b6000805460408051637bb20d2f60e11b81527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247600482015290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156111c057600080fd5b60008380156115bd576001841680156115385785925061153c565b8392505b50600283046002850494505b84156115b757858602868782041461155f57600080fd5b8181018181101561156f57600080fd5b85900496505060018516156115ac57858302838782041415871515161561159557600080fd5b818101818110156115a557600080fd5b8590049350505b600285049450611548565b506115d3565b8380156115cd57600092506115d1565b8392505b505b509392505050565b6000818484111561166a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561162f578181015183820152602001611617565b50505050905090810190601f16801561165c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836116c15760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561162f578181015183820152602001611617565b5060008385816116cd57fe5b0495945050505050565b60405180610100016040528060006001600160a01b03168152602001600080191681526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b805161046b81611b7e565b60008083601f840112611744578182fd5b50813567ffffffffffffffff81111561175b578182fd5b602083019150836020808302850101111561177557600080fd5b9250929050565b8035801515811461046b57600080fd5b60006020828403121561179d578081fd5b813561114b81611b7e565b600080604083850312156117ba578081fd5b82356117c581611b7e565b946020939093013593505050565b600080600080604085870312156117e8578182fd5b843567ffffffffffffffff808211156117ff578384fd5b61180b88838901611733565b90965094506020870135915080821115611823578384fd5b5061183087828801611733565b95989497509550505050565b60006020828403121561184d578081fd5b61114b8261177c565b600060208284031215611867578081fd5b5035919050565b60008060408385031215611880578182fd5b823591506118906020840161177c565b90509250929050565b6000806000604084860312156118ad578283fd5b83356118b881611b7e565b9250602084013567ffffffffffffffff808211156118d4578384fd5b818601915086601f8301126118e7578384fd5b8135818111156118f5578485fd5b876020828501011115611906578485fd5b6020830194508093505050509250925092565b600061010080838503121561192c578182fd5b6040519081019067ffffffffffffffff8211818310171561194957fe5b8160405261195684611728565b81526020840151602082015260408401516040820152606084015160608201526080840151608082015260a084015160a082015260c084015160c082015260e084015160e0820152809250505092915050565b6000602082840312156119ba578081fd5b5051919050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b60208082526023908201527f49737375616e6365207261746520756e646572206d696e696d756d20616c6c6f6040820152621dd95960ea1b606082015260800190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252600c908201526b69737375616e63655261746560a01b604082015260600190565b60208082526023908201527f43616c6c6572206d75737420626520746865207374616b696e6720636f6e74726040820152621858dd60ea1b606082015260800190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461086b57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206d75737420626520436f6e74726f6c6c657220676f7665726e6f7243616c6c6572206d7573742062652074686520696d706c656d656e746174696f6ea2646970667358221220a002cd24dc390f17b6944d68d32e345ae62f4f424f5cff28d60a4cf57180d93864736f6c63430007040033

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.