Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
RewardsManager
Compiler Version
v0.7.6+commit.7338295f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;
pragma abicoder v2;
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
import { GraphUpgradeable } from "../upgrades/GraphUpgradeable.sol";
import { Managed } from "../governance/Managed.sol";
import { MathUtils } from "../staking/libs/MathUtils.sol";
import { IGraphToken } from "../token/IGraphToken.sol";
import { RewardsManagerV5Storage } from "./RewardsManagerStorage.sol";
import { IRewardsManager } from "./IRewardsManager.sol";
import { IRewardsIssuer } from "./IRewardsIssuer.sol";
/**
* @title Rewards Manager Contract
* @dev Tracks how inflationary GRT rewards should be handed out. Relies on the Curation contract
* and the Staking contract. Signaled GRT in Curation determine what percentage of the tokens go
* towards each subgraph. Then each Subgraph can have multiple Indexers Staked on it. Thus, the
* total rewards for the Subgraph are split up for each Indexer based on much they have Staked on
* that Subgraph.
*
* Note:
* The contract provides getter functions to query the state of accrued rewards:
* - getAccRewardsPerSignal
* - getAccRewardsForSubgraph
* - getAccRewardsPerAllocatedToken
* - getRewards
* These functions may overestimate the actual rewards due to changes in the total supply
* until the actual takeRewards function is called.
*/
contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsManager {
using SafeMath for uint256;
/// @dev Fixed point scaling factor used for decimals in reward calculations
uint256 private constant FIXED_POINT_SCALING_FACTOR = 1e18;
// -- Events --
/**
* @dev Emitted when rewards are assigned to an indexer.
* @dev We use the Horizon prefix to change the event signature which makes network subgraph development much easier
*/
event HorizonRewardsAssigned(address indexed indexer, address indexed allocationID, uint256 amount);
/**
* @dev Emitted when rewards are denied to an indexer
* @param indexer Address of the indexer being denied rewards
* @param allocationID Address of the allocation being denied rewards
*/
event RewardsDenied(address indexed indexer, address indexed allocationID);
/**
* @dev Emitted when a subgraph is denied for claiming rewards
* @param subgraphDeploymentID Subgraph deployment ID being denied
* @param sinceBlock Block number since when the subgraph is denied
*/
event RewardsDenylistUpdated(bytes32 indexed subgraphDeploymentID, uint256 sinceBlock);
/**
* @dev Emitted when the subgraph service is set
*/
event SubgraphServiceSet(address indexed oldSubgraphService, address indexed newSubgraphService);
// -- Modifiers --
/**
* @dev Modifier to restrict access to the subgraph availability oracle only
*/
modifier onlySubgraphAvailabilityOracle() {
require(msg.sender == address(subgraphAvailabilityOracle), "Caller must be the subgraph availability oracle");
_;
}
/**
* @notice Initialize this contract
* @param _controller Address of the controller contract
*/
function initialize(address _controller) external onlyImpl {
Managed._initialize(_controller);
}
// -- Config --
/**
* @dev Sets the GRT issuance per block.
* The issuance is defined as a fixed amount of rewards per block in GRT.
* Whenever this function is called in layer 2, the updateL2MintAllowance function
* _must_ be called on the L1GraphTokenGateway in L1, to ensure the bridge can mint the
* right amount of tokens.
* @param _issuancePerBlock Issuance expressed in GRT per block (scaled by 1e18)
*/
function setIssuancePerBlock(uint256 _issuancePerBlock) external override onlyGovernor {
_setIssuancePerBlock(_issuancePerBlock);
}
/**
* @dev Sets the GRT issuance per block.
* The issuance is defined as a fixed amount of rewards per block in GRT.
* @param _issuancePerBlock Issuance expressed in GRT per block (scaled by 1e18)
*/
function _setIssuancePerBlock(uint256 _issuancePerBlock) private {
// Called since `issuance per block` will change
updateAccRewardsPerSignal();
issuancePerBlock = _issuancePerBlock;
emit ParameterUpdated("issuancePerBlock");
}
/**
* @notice Sets the subgraph oracle allowed to deny 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");
}
/**
* @notice Sets the minimum signaled tokens on a subgraph to start accruing rewards
* @dev Can be set to zero which means that this feature is not being used
* @param _minimumSubgraphSignal Minimum signaled tokens
*/
function setMinimumSubgraphSignal(uint256 _minimumSubgraphSignal) external override {
// Caller can be the SAO or the governor
require(
msg.sender == address(subgraphAvailabilityOracle) || msg.sender == controller.getGovernor(),
"Not authorized"
);
minimumSubgraphSignal = _minimumSubgraphSignal;
emit ParameterUpdated("minimumSubgraphSignal");
}
function setSubgraphService(address _subgraphService) external override onlyGovernor {
address oldSubgraphService = address(subgraphService);
subgraphService = IRewardsIssuer(_subgraphService);
emit SubgraphServiceSet(oldSubgraphService, _subgraphService);
}
// -- Denylist --
/**
* @notice Denies to claim rewards for a subgraph
* @dev 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 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);
}
/**
* @notice Tells if subgraph is in deny list
* @param _subgraphDeploymentID Subgraph deployment ID to check
* @return Whether the subgraph is denied for claiming rewards or not
*/
function isDenied(bytes32 _subgraphDeploymentID) public view override returns (bool) {
return denylist[_subgraphDeploymentID] > 0;
}
// -- Getters --
/**
* @notice Gets the issuance of rewards per signal since last updated
* @dev Linear formula: `x = r * t`
*
* Notation:
* t: time steps are in blocks since last updated
* x: newly accrued rewards tokens for the period `t`
*
* @return newly accrued rewards per signal since last update, scaled by FIXED_POINT_SCALING_FACTOR
*/
function getNewRewardsPerSignal() public view override 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;
}
// ...or if issuance is zero
if (issuancePerBlock == 0) {
return 0;
}
// Zero issuance if no signalled tokens
IGraphToken graphToken = graphToken();
uint256 signalledTokens = graphToken.balanceOf(address(curation()));
if (signalledTokens == 0) {
return 0;
}
uint256 x = issuancePerBlock.mul(t);
// Get the new issuance per signalled token
// We multiply the decimals to keep the precision as fixed-point number
return x.mul(FIXED_POINT_SCALING_FACTOR).div(signalledTokens);
}
/**
* @notice Gets the currently accumulated rewards per signal
* @return Currently accumulated rewards per signal
*/
function getAccRewardsPerSignal() public view override returns (uint256) {
return accRewardsPerSignal.add(getNewRewardsPerSignal());
}
/**
* @notice Gets the accumulated rewards for the subgraph
* @param _subgraphDeploymentID Subgraph deployment
* @return Accumulated rewards for subgraph
*/
function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID) public view override returns (uint256) {
Subgraph storage subgraph = subgraphs[_subgraphDeploymentID];
// Get tokens signalled on the subgraph
uint256 subgraphSignalledTokens = curation().getCurationPoolTokens(_subgraphDeploymentID);
// Only accrue rewards if over a threshold
uint256 newRewards = (subgraphSignalledTokens >= minimumSubgraphSignal) // Accrue new rewards since last snapshot
? getAccRewardsPerSignal().sub(subgraph.accRewardsPerSignalSnapshot).mul(subgraphSignalledTokens).div(
FIXED_POINT_SCALING_FACTOR
)
: 0;
return subgraph.accRewardsForSubgraph.add(newRewards);
}
/**
* @notice 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 view override returns (uint256, uint256) {
Subgraph storage subgraph = subgraphs[_subgraphDeploymentID];
uint256 accRewardsForSubgraph = getAccRewardsForSubgraph(_subgraphDeploymentID);
uint256 newRewardsForSubgraph = MathUtils.diffOrZero(
accRewardsForSubgraph,
subgraph.accRewardsForSubgraphSnapshot
);
// There are two contributors to subgraph allocated tokens:
// - the legacy allocations on the legacy staking contract
// - the new allocations on the subgraph service
uint256 subgraphAllocatedTokens = 0;
address[2] memory rewardsIssuers = [address(staking()), address(subgraphService)];
for (uint256 i = 0; i < rewardsIssuers.length; i++) {
if (rewardsIssuers[i] != address(0)) {
subgraphAllocatedTokens += IRewardsIssuer(rewardsIssuers[i]).getSubgraphAllocatedTokens(
_subgraphDeploymentID
);
}
}
if (subgraphAllocatedTokens == 0) {
return (0, accRewardsForSubgraph);
}
uint256 newRewardsPerAllocatedToken = newRewardsForSubgraph.mul(FIXED_POINT_SCALING_FACTOR).div(
subgraphAllocatedTokens
);
return (subgraph.accRewardsPerAllocatedToken.add(newRewardsPerAllocatedToken), accRewardsForSubgraph);
}
// -- Updates --
/**
* @notice Updates the accumulated rewards per signal and save checkpoint block number
* @dev Must be called before `issuancePerBlock` 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;
}
/**
* @notice Triggers an update of rewards for a subgraph
* @dev Must be called before `signalled GRT` on a subgraph changes.
* 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;
}
/**
* @notice Triggers an update of rewards for a subgraph
* @dev Must be called before allocation on a subgraph changes.
* 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.
* The allocation could be a legacy allocation or a new subgraph service allocation.
* Returns 0 if the allocation is not active.
* @param _allocationID Allocation
* @return Rewards amount for an allocation
*/
function getRewards(address _rewardsIssuer, address _allocationID) external view override returns (uint256) {
require(
_rewardsIssuer == address(staking()) || _rewardsIssuer == address(subgraphService),
"Not a rewards issuer"
);
(
bool isActive,
,
bytes32 subgraphDeploymentId,
uint256 tokens,
uint256 alloAccRewardsPerAllocatedToken,
uint256 accRewardsPending
) = IRewardsIssuer(_rewardsIssuer).getAllocationData(_allocationID);
if (!isActive) {
return 0;
}
(uint256 accRewardsPerAllocatedToken, ) = getAccRewardsPerAllocatedToken(subgraphDeploymentId);
return
accRewardsPending.add(_calcRewards(tokens, alloAccRewardsPerAllocatedToken, accRewardsPerAllocatedToken));
}
/**
* @dev Calculate rewards for a given accumulated rewards per allocated token.
* @param _tokens Tokens allocated
* @param _accRewardsPerAllocatedToken Allocation accumulated rewards per token
* @return Rewards amount
*/
function calcRewards(
uint256 _tokens,
uint256 _accRewardsPerAllocatedToken
) external pure override returns (uint256) {
return _accRewardsPerAllocatedToken.mul(_tokens).div(FIXED_POINT_SCALING_FACTOR);
}
/**
* @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(FIXED_POINT_SCALING_FACTOR);
}
/**
* @dev Pull rewards from the contract for a particular allocation.
* This function can only be called by an authorized rewards issuer which are
* the staking contract (for legacy allocations), and the subgraph service (for new allocations).
* This function will mint the necessary tokens to reward based on the inflation calculation.
* Mints 0 tokens if the allocation is not active.
* @param _allocationID Allocation
* @return Assigned rewards amount
*/
function takeRewards(address _allocationID) external override returns (uint256) {
address rewardsIssuer = msg.sender;
require(
rewardsIssuer == address(staking()) || rewardsIssuer == address(subgraphService),
"Caller must be a rewards issuer"
);
(
bool isActive,
address indexer,
bytes32 subgraphDeploymentID,
uint256 tokens,
uint256 accRewardsPerAllocatedToken,
uint256 accRewardsPending
) = IRewardsIssuer(rewardsIssuer).getAllocationData(_allocationID);
uint256 updatedAccRewardsPerAllocatedToken = onSubgraphAllocationUpdate(subgraphDeploymentID);
// Do not do rewards on denied subgraph deployments ID
if (isDenied(subgraphDeploymentID)) {
emit RewardsDenied(indexer, _allocationID);
return 0;
}
uint256 rewards = 0;
if (isActive) {
// Calculate rewards accrued by this allocation
rewards = accRewardsPending.add(
_calcRewards(tokens, accRewardsPerAllocatedToken, updatedAccRewardsPerAllocatedToken)
);
if (rewards > 0) {
// Mint directly to rewards issuer for the reward amount
// The rewards issuer contract will do bookkeeping of the reward and
// assign in proportion to each stakeholder incentive
graphToken().mint(rewardsIssuer, rewards);
}
}
emit HorizonRewardsAssigned(indexer, _allocationID, rewards);
return rewards;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.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, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
/**
* @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) {
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, reverting 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) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* 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);
return a - b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* 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);
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* 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;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.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);
}// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2020, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Originally copied from: * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-peripherals * * MODIFIED from Offchain Labs' implementation: * - Changed solidity version to 0.7.6 ([email protected]) * */ pragma solidity ^0.7.6 || 0.8.27; interface ITokenGateway { /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated // event OutboundTransferInitiated( // address token, // address indexed _from, // address indexed _to, // uint256 indexed _transferId, // uint256 _amount, // bytes _data // ); /// @notice event deprecated in favor of DepositFinalized and WithdrawalFinalized // event InboundTransferFinalized( // address token, // address indexed _from, // address indexed _to, // uint256 indexed _transferId, // uint256 _amount, // bytes _data // ); function outboundTransfer( address token, address to, uint256 amunt, uint256 maxas, uint256 gasPiceBid, bytes calldata data ) external payable returns (bytes memory); function finalizeInboundTransfer( address token, address from, address to, uint256 amount, bytes calldata data ) external payable; /** * @notice Calculate the address used when bridging an ERC20 token * @dev the L1 and L2 address oracles may not always be in sync. * For example, a custom token may have been registered but not deployed or the contract self destructed. * @param l1ERC20 address of L1 token * @return L2 address of a bridged ERC20 token */ function calculateL2TokenAddress(address l1ERC20) external view returns (address); }
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
pragma abicoder v2;
/**
* @title Multicall interface
* @notice Enables calling multiple methods in a single call to the contract
*/
interface IMulticall {
/**
* @notice Call multiple functions in the current contract and return the data from all of them if they all succeed
* @param data The encoded function data for each of the calls to make to this contract
* @return results The results from each of the calls passed in via data
*/
function multicall(bytes[] calldata data) external returns (bytes[] memory results);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
/**
* @title Curation Interface
* @dev Interface for the Curation contract (and L2Curation too)
*/
interface ICuration {
// -- Configuration --
/**
* @notice Update the default reserve ratio to `_defaultReserveRatio`
* @param _defaultReserveRatio Reserve ratio (in PPM)
*/
function setDefaultReserveRatio(uint32 _defaultReserveRatio) external;
/**
* @notice Update the minimum deposit amount needed to intialize a new subgraph
* @param _minimumCurationDeposit Minimum amount of tokens required deposit
*/
function setMinimumCurationDeposit(uint256 _minimumCurationDeposit) external;
/**
* @notice Set the curation tax percentage to charge when a curator deposits GRT tokens.
* @param _percentage Curation tax percentage charged when depositing GRT tokens
*/
function setCurationTaxPercentage(uint32 _percentage) external;
/**
* @notice Set the master copy to use as clones for the curation token.
* @param _curationTokenMaster Address of implementation contract to use for curation tokens
*/
function setCurationTokenMaster(address _curationTokenMaster) external;
// -- Curation --
/**
* @notice Deposit Graph Tokens in exchange for signal of a SubgraphDeployment curation pool.
* @param _subgraphDeploymentID Subgraph deployment pool from where to mint signal
* @param _tokensIn Amount of Graph Tokens to deposit
* @param _signalOutMin Expected minimum amount of signal to receive
* @return Amount of signal minted
* @return Amount of curation tax burned
*/
function mint(
bytes32 _subgraphDeploymentID,
uint256 _tokensIn,
uint256 _signalOutMin
) external returns (uint256, uint256);
/**
* @notice Burn _signal from the SubgraphDeployment curation pool
* @param _subgraphDeploymentID SubgraphDeployment the curator is returning signal
* @param _signalIn Amount of signal to return
* @param _tokensOutMin Expected minimum amount of tokens to receive
* @return Tokens returned
*/
function burn(bytes32 _subgraphDeploymentID, uint256 _signalIn, uint256 _tokensOutMin) external returns (uint256);
/**
* @notice Assign Graph Tokens collected as curation fees to the curation pool reserve.
* @param _subgraphDeploymentID SubgraphDeployment where funds should be allocated as reserves
* @param _tokens Amount of Graph Tokens to add to reserves
*/
function collect(bytes32 _subgraphDeploymentID, uint256 _tokens) external;
// -- Getters --
/**
* @notice Check if any GRT tokens are deposited for a SubgraphDeployment.
* @param _subgraphDeploymentID SubgraphDeployment to check if curated
* @return True if curated, false otherwise
*/
function isCurated(bytes32 _subgraphDeploymentID) external view returns (bool);
/**
* @notice Get the amount of signal a curator has in a curation pool.
* @param _curator Curator owning the signal tokens
* @param _subgraphDeploymentID Subgraph deployment curation pool
* @return Amount of signal owned by a curator for the subgraph deployment
*/
function getCuratorSignal(address _curator, bytes32 _subgraphDeploymentID) external view returns (uint256);
/**
* @notice Get the amount of signal in a curation pool.
* @param _subgraphDeploymentID Subgraph deployment curation pool
* @return Amount of signal minted for the subgraph deployment
*/
function getCurationPoolSignal(bytes32 _subgraphDeploymentID) external view returns (uint256);
/**
* @notice Get the amount of token reserves in a curation pool.
* @param _subgraphDeploymentID Subgraph deployment curation pool
* @return Amount of token reserves in the curation pool
*/
function getCurationPoolTokens(bytes32 _subgraphDeploymentID) external view returns (uint256);
/**
* @notice Calculate amount of signal that can be bought with tokens in a curation pool.
* This function considers and excludes the deposit tax.
* @param _subgraphDeploymentID Subgraph deployment to mint signal
* @param _tokensIn Amount of tokens used to mint signal
* @return Amount of signal that can be bought
* @return Amount of tokens that will be burned as curation tax
*/
function tokensToSignal(bytes32 _subgraphDeploymentID, uint256 _tokensIn) external view returns (uint256, uint256);
/**
* @notice Calculate number of tokens to get when burning signal from a curation pool.
* @param _subgraphDeploymentID Subgraph deployment to burn signal
* @param _signalIn Amount of signal to burn
* @return Amount of tokens to get for the specified amount of signal
*/
function signalToTokens(bytes32 _subgraphDeploymentID, uint256 _signalIn) external view returns (uint256);
/**
* @notice Tax charged when curators deposit funds.
* Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%)
* @return Curation tax percentage expressed in PPM
*/
function curationTaxPercentage() external view returns (uint32);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
/**
* @title Interface for GNS
*/
interface IGNS {
// -- Pool --
/**
* @dev The SubgraphData struct holds information about subgraphs
* and their signal; both nSignal (i.e. name signal at the GNS level)
* and vSignal (i.e. version signal at the Curation contract level)
*/
struct SubgraphData {
uint256 vSignal; // The token of the subgraph-deployment bonding curve
uint256 nSignal; // The token of the subgraph bonding curve
mapping(address => uint256) curatorNSignal;
bytes32 subgraphDeploymentID;
uint32 __DEPRECATED_reserveRatio; // solhint-disable-line var-name-mixedcase
bool disabled;
uint256 withdrawableGRT;
}
/**
* @dev The LegacySubgraphKey struct holds the account and sequence ID
* used to generate subgraph IDs in legacy subgraphs.
*/
struct LegacySubgraphKey {
address account;
uint256 accountSeqID;
}
// -- Configuration --
/**
* @notice Approve curation contract to pull funds.
*/
function approveAll() external;
/**
* @notice Set the owner fee percentage. This is used to prevent a subgraph owner to drain all
* the name curators tokens while upgrading or deprecating and is configurable in parts per million.
* @param _ownerTaxPercentage Owner tax percentage
*/
function setOwnerTaxPercentage(uint32 _ownerTaxPercentage) external;
// -- Publishing --
/**
* @notice Allows a graph account to set a default name
* @param _graphAccount Account that is setting its name
* @param _nameSystem Name system account already has ownership of a name in
* @param _nameIdentifier The unique identifier that is used to identify the name in the system
* @param _name The name being set as default
*/
function setDefaultName(
address _graphAccount,
uint8 _nameSystem,
bytes32 _nameIdentifier,
string calldata _name
) external;
/**
* @notice Allows a subgraph owner to update the metadata of a subgraph they have published
* @param _subgraphID Subgraph ID
* @param _subgraphMetadata IPFS hash for the subgraph metadata
*/
function updateSubgraphMetadata(uint256 _subgraphID, bytes32 _subgraphMetadata) external;
/**
* @notice Publish a new subgraph.
* @param _subgraphDeploymentID Subgraph deployment for the subgraph
* @param _versionMetadata IPFS hash for the subgraph version metadata
* @param _subgraphMetadata IPFS hash for the subgraph metadata
*/
function publishNewSubgraph(
bytes32 _subgraphDeploymentID,
bytes32 _versionMetadata,
bytes32 _subgraphMetadata
) external;
/**
* @notice Publish a new version of an existing subgraph.
* @param _subgraphID Subgraph ID
* @param _subgraphDeploymentID Subgraph deployment ID of the new version
* @param _versionMetadata IPFS hash for the subgraph version metadata
*/
function publishNewVersion(uint256 _subgraphID, bytes32 _subgraphDeploymentID, bytes32 _versionMetadata) external;
/**
* @notice Deprecate a subgraph. The bonding curve is destroyed, the vSignal is burned, and the GNS
* contract holds the GRT from burning the vSignal, which all curators can withdraw manually.
* Can only be done by the subgraph owner.
* @param _subgraphID Subgraph ID
*/
function deprecateSubgraph(uint256 _subgraphID) external;
// -- Curation --
/**
* @notice Deposit GRT into a subgraph and mint signal.
* @param _subgraphID Subgraph ID
* @param _tokensIn The amount of tokens the nameCurator wants to deposit
* @param _nSignalOutMin Expected minimum amount of name signal to receive
*/
function mintSignal(uint256 _subgraphID, uint256 _tokensIn, uint256 _nSignalOutMin) external;
/**
* @notice Burn signal for a subgraph and return the GRT.
* @param _subgraphID Subgraph ID
* @param _nSignal The amount of nSignal the nameCurator wants to burn
* @param _tokensOutMin Expected minimum amount of tokens to receive
*/
function burnSignal(uint256 _subgraphID, uint256 _nSignal, uint256 _tokensOutMin) external;
/**
* @notice Move subgraph signal from sender to `_recipient`
* @param _subgraphID Subgraph ID
* @param _recipient Address to send the signal to
* @param _amount The amount of nSignal to transfer
*/
function transferSignal(uint256 _subgraphID, address _recipient, uint256 _amount) external;
/**
* @notice Withdraw tokens from a deprecated subgraph.
* When the subgraph is deprecated, any curator can call this function and
* withdraw the GRT they are entitled for its original deposit
* @param _subgraphID Subgraph ID
*/
function withdraw(uint256 _subgraphID) external;
// -- Getters --
/**
* @notice Return the owner of a subgraph.
* @param _tokenID Subgraph ID
* @return Owner address
*/
function ownerOf(uint256 _tokenID) external view returns (address);
/**
* @notice Return the total signal on the subgraph.
* @param _subgraphID Subgraph ID
* @return Total signal on the subgraph
*/
function subgraphSignal(uint256 _subgraphID) external view returns (uint256);
/**
* @notice Return the total tokens on the subgraph at current value.
* @param _subgraphID Subgraph ID
* @return Total tokens on the subgraph
*/
function subgraphTokens(uint256 _subgraphID) external view returns (uint256);
/**
* @notice Calculate subgraph signal to be returned for an amount of tokens.
* @param _subgraphID Subgraph ID
* @param _tokensIn Tokens being exchanged for subgraph signal
* @return Amount of subgraph signal and curation tax
*/
function tokensToNSignal(uint256 _subgraphID, uint256 _tokensIn) external view returns (uint256, uint256, uint256);
/**
* @notice Calculate tokens returned for an amount of subgraph signal.
* @param _subgraphID Subgraph ID
* @param _nSignalIn Subgraph signal being exchanged for tokens
* @return Amount of tokens returned for an amount of subgraph signal
*/
function nSignalToTokens(uint256 _subgraphID, uint256 _nSignalIn) external view returns (uint256, uint256);
/**
* @notice Calculate subgraph signal to be returned for an amount of subgraph deployment signal.
* @param _subgraphID Subgraph ID
* @param _vSignalIn Amount of subgraph deployment signal to exchange for subgraph signal
* @return Amount of subgraph signal that can be bought
*/
function vSignalToNSignal(uint256 _subgraphID, uint256 _vSignalIn) external view returns (uint256);
/**
* @notice Calculate subgraph deployment signal to be returned for an amount of subgraph signal.
* @param _subgraphID Subgraph ID
* @param _nSignalIn Subgraph signal being exchanged for subgraph deployment signal
* @return Amount of subgraph deployment signal that can be returned
*/
function nSignalToVSignal(uint256 _subgraphID, uint256 _nSignalIn) external view returns (uint256);
/**
* @notice Get the amount of subgraph signal a curator has.
* @param _subgraphID Subgraph ID
* @param _curator Curator address
* @return Amount of subgraph signal owned by a curator
*/
function getCuratorSignal(uint256 _subgraphID, address _curator) external view returns (uint256);
/**
* @notice Return whether a subgraph is published.
* @param _subgraphID Subgraph ID
* @return Return true if subgraph is currently published
*/
function isPublished(uint256 _subgraphID) external view returns (bool);
/**
* @notice Return whether a subgraph is a legacy subgraph (created before subgraph NFTs).
* @param _subgraphID Subgraph ID
* @return Return true if subgraph is a legacy subgraph
*/
function isLegacySubgraph(uint256 _subgraphID) external view returns (bool);
/**
* @notice Returns account and sequence ID for a legacy subgraph (created before subgraph NFTs).
* @param _subgraphID Subgraph ID
* @return account Account that created the subgraph (or 0 if it's not a legacy subgraph)
* @return seqID Sequence number for the subgraph
*/
function getLegacySubgraphKey(uint256 _subgraphID) external view returns (address account, uint256 seqID);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
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);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
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);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
import { IController } from "./IController.sol";
/**
* @title Managed Interface
* @dev Interface for contracts that can be managed by a controller.
*/
interface IManaged {
/**
* @notice Set the controller that manages this contract
* @dev Only the current controller can set a new controller
* @param _controller Address of the new controller
*/
function setController(address _controller) external;
/**
* @notice Sync protocol contract addresses from the Controller registry
* @dev This function will cache all the contracts using the latest addresses.
* Anyone can call the function whenever a Proxy contract change in the
* controller to ensure the protocol is using the latest version.
*/
function syncAllContracts() external;
/**
* @notice Get the Controller that manages this contract
* @return The Controller as an IController interface
*/
function controller() external view returns (IController);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6;
import { IController } from "./IController.sol";
import { ICuration } from "../curation/ICuration.sol";
import { IEpochManager } from "../epochs/IEpochManager.sol";
import { IRewardsManager } from "../rewards/IRewardsManager.sol";
import { IStaking } from "../staking/IStaking.sol";
import { IGraphToken } from "../token/IGraphToken.sol";
import { ITokenGateway } from "../arbitrum/ITokenGateway.sol";
import { IGNS } from "../discovery/IGNS.sol";
import { IManaged } from "./IManaged.sol";
/**
* @title Graph Managed contract
* @dev The Managed contract provides an interface to interact with the Controller.
* It also provides local caching for contract addresses. This mechanism relies on calling the
* public `syncAllContracts()` function whenever a contract changes in the controller.
*
* Inspired by Livepeer:
* https://github.com/livepeer/protocol/blob/streamflow/contracts/Controller.sol
*/
abstract contract Managed is IManaged {
// -- State --
/// Controller that manages this contract
IController public override controller;
/// @dev Cache for the addresses of the contracts retrieved from the controller
mapping(bytes32 => address) private _addressCache;
/// @dev Gap for future storage variables
uint256[10] private __gap;
// Immutables
bytes32 private immutable CURATION = keccak256("Curation");
bytes32 private immutable EPOCH_MANAGER = keccak256("EpochManager");
bytes32 private immutable REWARDS_MANAGER = keccak256("RewardsManager");
bytes32 private immutable STAKING = keccak256("Staking");
bytes32 private immutable GRAPH_TOKEN = keccak256("GraphToken");
bytes32 private immutable GRAPH_TOKEN_GATEWAY = keccak256("GraphTokenGateway");
bytes32 private immutable GNS = keccak256("GNS");
// -- Events --
/// Emitted when a contract parameter has been updated
event ParameterUpdated(string param);
/// Emitted when the controller address has been set
event SetController(address controller);
/// Emitted when contract with `nameHash` is synced to `contractAddress`.
event ContractSynced(bytes32 indexed nameHash, address contractAddress);
// -- Modifiers --
/**
* @dev Revert if the controller is paused or partially paused
*/
function _notPartialPaused() internal view {
require(!controller.paused(), "Paused");
require(!controller.partialPaused(), "Partial-paused");
}
/**
* @dev Revert if the controller is paused
*/
function _notPaused() internal view virtual {
require(!controller.paused(), "Paused");
}
/**
* @dev Revert if the caller is not the governor
*/
function _onlyGovernor() internal view {
require(msg.sender == controller.getGovernor(), "Only Controller governor");
}
/**
* @dev Revert if the caller is not the Controller
*/
function _onlyController() internal view {
require(msg.sender == address(controller), "Caller must be Controller");
}
/**
* @dev Revert if the controller is paused or partially paused
*/
modifier notPartialPaused() {
_notPartialPaused();
_;
}
/**
* @dev Revert if the controller is paused
*/
modifier notPaused() {
_notPaused();
_;
}
/**
* @dev Revert if the caller is not the Controller
*/
modifier onlyController() {
_onlyController();
_;
}
/**
* @dev Revert if the caller is not the governor
*/
modifier onlyGovernor() {
_onlyGovernor();
_;
}
// -- Functions --
/**
* @dev Initialize a Managed contract
* @param _controller Address for the Controller that manages this contract
*/
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 override 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(_resolveContract(CURATION));
}
/**
* @dev Return EpochManager interface
* @return Epoch manager contract registered with Controller
*/
function epochManager() internal view returns (IEpochManager) {
return IEpochManager(_resolveContract(EPOCH_MANAGER));
}
/**
* @dev Return RewardsManager interface
* @return Rewards manager contract registered with Controller
*/
function rewardsManager() internal view returns (IRewardsManager) {
return IRewardsManager(_resolveContract(REWARDS_MANAGER));
}
/**
* @dev Return Staking interface
* @return Staking contract registered with Controller
*/
function staking() internal view returns (IStaking) {
return IStaking(_resolveContract(STAKING));
}
/**
* @dev Return GraphToken interface
* @return Graph token contract registered with Controller
*/
function graphToken() internal view returns (IGraphToken) {
return IGraphToken(_resolveContract(GRAPH_TOKEN));
}
/**
* @dev Return GraphTokenGateway (L1 or L2) interface
* @return Graph token gateway contract registered with Controller
*/
function graphTokenGateway() internal view returns (ITokenGateway) {
return ITokenGateway(_resolveContract(GRAPH_TOKEN_GATEWAY));
}
/**
* @dev Return GNS (L1 or L2) interface.
* @return Address of the GNS contract registered with Controller, as an IGNS interface.
*/
function gns() internal view returns (IGNS) {
return IGNS(_resolveContract(GNS));
}
/**
* @dev Resolve a contract address from the cache or the Controller if not found.
* @param _nameHash keccak256 hash of the contract name
* @return Address of the contract
*/
function _resolveContract(bytes32 _nameHash) internal view returns (address) {
address contractAddress = _addressCache[_nameHash];
if (contractAddress == address(0)) {
contractAddress = controller.getContractProxy(_nameHash);
}
return contractAddress;
}
/**
* @dev Cache a contract address from the Controller registry.
* @param _nameHash keccak256 hash of the name of the contract to sync into the cache
*/
function _syncContract(bytes32 _nameHash) internal {
address contractAddress = controller.getContractProxy(_nameHash);
if (_addressCache[_nameHash] != contractAddress) {
_addressCache[_nameHash] = contractAddress;
emit ContractSynced(_nameHash, contractAddress);
}
}
/**
* @notice Sync protocol contract addresses from the Controller registry
* @dev This function will cache all the contracts using the latest addresses
* Anyone can call the function whenever a Proxy contract change in the
* controller to ensure the protocol is using the latest version
*/
function syncAllContracts() external override {
_syncContract(CURATION);
_syncContract(EPOCH_MANAGER);
_syncContract(REWARDS_MANAGER);
_syncContract(STAKING);
_syncContract(GRAPH_TOKEN);
_syncContract(GRAPH_TOKEN_GATEWAY);
_syncContract(GNS);
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
interface IRewardsIssuer {
/**
* @dev Get allocation data to calculate rewards issuance
*
* @param allocationId The allocation Id
* @return isActive Whether the allocation is active or not
* @return indexer The indexer address
* @return subgraphDeploymentId Subgraph deployment id for the allocation
* @return tokens Amount of allocated tokens
* @return accRewardsPerAllocatedToken Rewards snapshot
* @return accRewardsPending Snapshot of accumulated rewards from previous allocation resizing, pending to be claimed
*/
function getAllocationData(
address allocationId
)
external
view
returns (
bool isActive,
address indexer,
bytes32 subgraphDeploymentId,
uint256 tokens,
uint256 accRewardsPerAllocatedToken,
uint256 accRewardsPending
);
/**
* @notice Return the total amount of tokens allocated to subgraph.
* @param _subgraphDeploymentId Deployment Id for the subgraph
* @return Total tokens allocated to subgraph
*/
function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentId) external view returns (uint256);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
interface IRewardsManager {
/**
* @dev Stores accumulated rewards and snapshots related to a particular SubgraphDeployment.
*/
struct Subgraph {
uint256 accRewardsForSubgraph;
uint256 accRewardsForSubgraphSnapshot;
uint256 accRewardsPerSignalSnapshot;
uint256 accRewardsPerAllocatedToken;
}
// -- Config --
function setIssuancePerBlock(uint256 _issuancePerBlock) external;
function setMinimumSubgraphSignal(uint256 _minimumSubgraphSignal) external;
function setSubgraphService(address _subgraphService) external;
// -- Denylist --
function setSubgraphAvailabilityOracle(address _subgraphAvailabilityOracle) external;
function setDenied(bytes32 _subgraphDeploymentID, bool _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 _rewardsIssuer, address _allocationID) external view returns (uint256);
function calcRewards(uint256 _tokens, uint256 _accRewardsPerAllocatedToken) external pure 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);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
import { IRewardsIssuer } from "./IRewardsIssuer.sol";
import { IRewardsManager } from "./IRewardsManager.sol";
import { Managed } from "../governance/Managed.sol";
contract RewardsManagerV1Storage is Managed {
// -- State --
uint256 private __DEPRECATED_issuanceRate; // solhint-disable-line var-name-mixedcase
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;
}
contract RewardsManagerV2Storage is RewardsManagerV1Storage {
// Minimum amount of signaled tokens on a subgraph required to accrue rewards
uint256 public minimumSubgraphSignal;
}
contract RewardsManagerV3Storage is RewardsManagerV2Storage {
// Snapshot of the total supply of GRT when accRewardsPerSignal was last updated
uint256 private __DEPRECATED_tokenSupplySnapshot; // solhint-disable-line var-name-mixedcase
}
contract RewardsManagerV4Storage is RewardsManagerV3Storage {
// GRT issued for indexer rewards per block
uint256 public issuancePerBlock;
}
contract RewardsManagerV5Storage is RewardsManagerV4Storage {
// Address of the subgraph service
IRewardsIssuer public subgraphService;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.12 <0.8.0 || 0.8.27;
pragma abicoder v2;
import { IStakingBase } from "./IStakingBase.sol";
import { IStakingExtension } from "./IStakingExtension.sol";
import { IMulticall } from "../base/IMulticall.sol";
import { IManaged } from "../governance/IManaged.sol";
/**
* @title Interface for the Staking contract
* @notice This is the interface that should be used when interacting with the Staking contract.
* @dev Note that Staking doesn't actually inherit this interface. This is because of
* the custom setup of the Staking contract where part of the functionality is implemented
* in a separate contract (StakingExtension) to which calls are delegated through the fallback function.
*/
interface IStaking is IStakingBase, IStakingExtension, IMulticall, IManaged {}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.12 <0.8.0 || 0.8.27;
pragma abicoder v2;
import { IStakingData } from "./IStakingData.sol";
/**
* @title Base interface for the Staking contract.
* @dev This interface includes only what's implemented in the base Staking contract.
* It does not include the L1 and L2 specific functionality. It also does not include
* several functions that are implemented in the StakingExtension contract, and are called
* via delegatecall through the fallback function. See IStaking.sol for an interface
* that includes the full functionality.
*/
interface IStakingBase is IStakingData {
/**
* @dev Emitted when `indexer` stakes `tokens` amount.
*/
event StakeDeposited(address indexed indexer, uint256 tokens);
/**
* @dev Emitted when `indexer` unstaked and locked `tokens` amount until `until` block.
*/
event StakeLocked(address indexed indexer, uint256 tokens, uint256 until);
/**
* @dev Emitted when `indexer` withdrew `tokens` staked.
*/
event StakeWithdrawn(address indexed indexer, uint256 tokens);
/**
* @dev Emitted when `indexer` allocated `tokens` amount to `subgraphDeploymentID`
* during `epoch`.
* `allocationID` indexer derived address used to identify the allocation.
* `metadata` additional information related to the allocation.
*/
event AllocationCreated(
address indexed indexer,
bytes32 indexed subgraphDeploymentID,
uint256 epoch,
uint256 tokens,
address indexed allocationID,
bytes32 metadata
);
/**
* @dev Emitted when `indexer` close an allocation in `epoch` for `allocationID`.
* An amount of `tokens` get unallocated from `subgraphDeploymentID`.
* This event also emits the POI (proof of indexing) submitted by the indexer.
* `isPublic` is true if the sender was someone other than the indexer.
*/
event AllocationClosed(
address indexed indexer,
bytes32 indexed subgraphDeploymentID,
uint256 epoch,
uint256 tokens,
address indexed allocationID,
address sender,
bytes32 poi,
bool isPublic
);
/**
* @dev Emitted when `indexer` collects a rebate on `subgraphDeploymentID` for `allocationID`.
* `epoch` is the protocol epoch the rebate was collected on
* The rebate is for `tokens` amount which are being provided by `assetHolder`; `queryFees`
* is the amount up for rebate after `curationFees` are distributed and `protocolTax` is burnt.
* `queryRebates` is the amount distributed to the `indexer` with `delegationFees` collected
* and sent to the delegation pool.
*/
event RebateCollected(
address assetHolder,
address indexed indexer,
bytes32 indexed subgraphDeploymentID,
address indexed allocationID,
uint256 epoch,
uint256 tokens,
uint256 protocolTax,
uint256 curationFees,
uint256 queryFees,
uint256 queryRebates,
uint256 delegationRewards
);
/**
* @dev Emitted when `indexer` update the delegation parameters for its delegation pool.
*/
event DelegationParametersUpdated(
address indexed indexer,
uint32 indexingRewardCut,
uint32 queryFeeCut,
uint32 __DEPRECATED_cooldownBlocks // solhint-disable-line var-name-mixedcase
);
/**
* @dev Emitted when `indexer` set `operator` access.
*/
event SetOperator(address indexed indexer, address indexed operator, bool allowed);
/**
* @dev Emitted when `indexer` set an address to receive rewards.
*/
event SetRewardsDestination(address indexed indexer, address indexed destination);
/**
* @dev Emitted when `extensionImpl` was set as the address of the StakingExtension contract
* to which extended functionality is delegated.
*/
event ExtensionImplementationSet(address indexed extensionImpl);
/**
* @dev Possible states an allocation can be.
* States:
* - Null = indexer == address(0)
* - Active = not Null && tokens > 0
* - Closed = Active && closedAtEpoch != 0
*/
enum AllocationState {
Null,
Active,
Closed
}
/**
* @notice Initialize this contract.
* @param _controller Address of the controller that manages this contract
* @param _minimumIndexerStake Minimum amount of tokens that an indexer must stake
* @param _thawingPeriod Number of blocks that tokens get locked after unstaking
* @param _protocolPercentage Percentage of query fees that are burned as protocol fee (in PPM)
* @param _curationPercentage Percentage of query fees that are given to curators (in PPM)
* @param _maxAllocationEpochs The maximum number of epochs that an allocation can be active
* @param _delegationUnbondingPeriod The period in epochs that tokens get locked after undelegating
* @param _delegationRatio The ratio between an indexer's own stake and the delegation they can use
* @param _rebatesParameters Alpha and lambda parameters for rebates function
* @param _extensionImpl Address of the StakingExtension implementation
*/
function initialize(
address _controller,
uint256 _minimumIndexerStake,
uint32 _thawingPeriod,
uint32 _protocolPercentage,
uint32 _curationPercentage,
uint32 _maxAllocationEpochs,
uint32 _delegationUnbondingPeriod,
uint32 _delegationRatio,
RebatesParameters calldata _rebatesParameters,
address _extensionImpl
) external;
/**
* @notice Set the address of the StakingExtension implementation.
* @dev This function can only be called by the governor.
* @param _extensionImpl Address of the StakingExtension implementation
*/
function setExtensionImpl(address _extensionImpl) external;
/**
* @notice Set the address of the counterpart (L1 or L2) staking contract.
* @dev This function can only be called by the governor.
* @param _counterpart Address of the counterpart staking contract in the other chain, without any aliasing.
*/
function setCounterpartStakingAddress(address _counterpart) external;
/**
* @notice Set the minimum stake needed to be an Indexer
* @dev This function can only be called by the governor.
* @param _minimumIndexerStake Minimum amount of tokens that an indexer must stake
*/
function setMinimumIndexerStake(uint256 _minimumIndexerStake) external;
/**
* @notice Set the number of blocks that tokens get locked after unstaking
* @dev This function can only be called by the governor.
* @param _thawingPeriod Number of blocks that tokens get locked after unstaking
*/
function setThawingPeriod(uint32 _thawingPeriod) external;
/**
* @notice Set the curation percentage of query fees sent to curators.
* @dev This function can only be called by the governor.
* @param _percentage Percentage of query fees sent to curators
*/
function setCurationPercentage(uint32 _percentage) external;
/**
* @notice Set a protocol percentage to burn when collecting query fees.
* @dev This function can only be called by the governor.
* @param _percentage Percentage of query fees to burn as protocol fee
*/
function setProtocolPercentage(uint32 _percentage) external;
/**
* @notice Set the max time allowed for indexers to allocate on a subgraph
* before others are allowed to close the allocation.
* @dev This function can only be called by the governor.
* @param _maxAllocationEpochs Allocation duration limit in epochs
*/
function setMaxAllocationEpochs(uint32 _maxAllocationEpochs) external;
/**
* @notice Set the rebate parameters
* @dev This function can only be called by the governor.
* @param _alphaNumerator Numerator of `alpha`
* @param _alphaDenominator Denominator of `alpha`
* @param _lambdaNumerator Numerator of `lambda`
* @param _lambdaDenominator Denominator of `lambda`
*/
function setRebateParameters(
uint32 _alphaNumerator,
uint32 _alphaDenominator,
uint32 _lambdaNumerator,
uint32 _lambdaDenominator
) external;
/**
* @notice Authorize or unauthorize an address to be an operator for the caller.
* @param _operator Address to authorize or unauthorize
* @param _allowed Whether the operator is authorized or not
*/
function setOperator(address _operator, bool _allowed) external;
/**
* @notice Deposit tokens on the indexer's stake.
* The amount staked must be over the minimumIndexerStake.
* @param _tokens Amount of tokens to stake
*/
function stake(uint256 _tokens) external;
/**
* @notice Deposit tokens on the Indexer stake, on behalf of the Indexer.
* The amount staked must be over the minimumIndexerStake.
* @param _indexer Address of the indexer
* @param _tokens Amount of tokens to stake
*/
function stakeTo(address _indexer, uint256 _tokens) external;
/**
* @notice Unstake tokens from the indexer stake, lock them until the thawing period expires.
* @dev NOTE: The function accepts an amount greater than the currently staked tokens.
* If that happens, it will try to unstake the max amount of tokens it can.
* The reason for this behaviour is to avoid time conditions while the transaction
* is in flight.
* @param _tokens Amount of tokens to unstake
*/
function unstake(uint256 _tokens) external;
/**
* @notice Withdraw indexer tokens once the thawing period has passed.
*/
function withdraw() external;
/**
* @notice Set the destination where to send rewards for an indexer.
* @param _destination Rewards destination address. If set to zero, rewards will be restaked
*/
function setRewardsDestination(address _destination) external;
/**
* @notice Set the delegation parameters for the caller.
* @param _indexingRewardCut Percentage of indexing rewards left for the indexer
* @param _queryFeeCut Percentage of query fees left for the indexer
*/
function setDelegationParameters(
uint32 _indexingRewardCut,
uint32 _queryFeeCut,
uint32 // _cooldownBlocks, deprecated
) external;
/**
* @notice Allocate available tokens to a subgraph deployment.
* @param _subgraphDeploymentID ID of the SubgraphDeployment where tokens will be allocated
* @param _tokens Amount of tokens to allocate
* @param _allocationID The allocation identifier
* @param _metadata IPFS hash for additional information about the allocation
* @param _proof A 65-bytes Ethereum signed message of `keccak256(indexerAddress,allocationID)`
*/
function allocate(
bytes32 _subgraphDeploymentID,
uint256 _tokens,
address _allocationID,
bytes32 _metadata,
bytes calldata _proof
) external;
/**
* @notice Allocate available tokens to a subgraph deployment from and indexer's stake.
* The caller must be the indexer or the indexer's operator.
* @param _indexer Indexer address to allocate funds from.
* @param _subgraphDeploymentID ID of the SubgraphDeployment where tokens will be allocated
* @param _tokens Amount of tokens to allocate
* @param _allocationID The allocation identifier
* @param _metadata IPFS hash for additional information about the allocation
* @param _proof A 65-bytes Ethereum signed message of `keccak256(indexerAddress,allocationID)`
*/
function allocateFrom(
address _indexer,
bytes32 _subgraphDeploymentID,
uint256 _tokens,
address _allocationID,
bytes32 _metadata,
bytes calldata _proof
) external;
/**
* @notice Close an allocation and free the staked tokens.
* To be eligible for rewards a proof of indexing must be presented.
* Presenting a bad proof is subject to slashable condition.
* To opt out of rewards set _poi to 0x0
* @param _allocationID The allocation identifier
* @param _poi Proof of indexing submitted for the allocated period
*/
function closeAllocation(address _allocationID, bytes32 _poi) external;
/**
* @notice Collect query fees from state channels and assign them to an allocation.
* Funds received are only accepted from a valid sender.
* @dev To avoid reverting on the withdrawal from channel flow this function will:
* 1) Accept calls with zero tokens.
* 2) Accept calls after an allocation passed the dispute period, in that case, all
* the received tokens are burned.
* @param _tokens Amount of tokens to collect
* @param _allocationID Allocation where the tokens will be assigned
*/
function collect(uint256 _tokens, address _allocationID) external;
/**
* @notice Return true if operator is allowed for indexer.
* @param _operator Address of the operator
* @param _indexer Address of the indexer
* @return True if operator is allowed for indexer, false otherwise
*/
function isOperator(address _operator, address _indexer) external view returns (bool);
/**
* @notice Getter that returns if an indexer has any stake.
* @param _indexer Address of the indexer
* @return True if indexer has staked tokens
*/
function hasStake(address _indexer) external view returns (bool);
/**
* @notice Get the total amount of tokens staked by the indexer.
* @param _indexer Address of the indexer
* @return Amount of tokens staked by the indexer
*/
function getIndexerStakedTokens(address _indexer) external view returns (uint256);
/**
* @notice Get the total amount of tokens available to use in allocations.
* This considers the indexer stake and delegated tokens according to delegation ratio
* @param _indexer Address of the indexer
* @return Amount of tokens available to allocate including delegation
*/
function getIndexerCapacity(address _indexer) external view returns (uint256);
/**
* @notice Return the allocation by ID.
* @param _allocationID Address used as allocation identifier
* @return Allocation data
*/
function getAllocation(address _allocationID) external view returns (Allocation memory);
/**
* @dev New function to get the allocation data for the rewards manager
* @dev Note that this is only to make tests pass, as the staking contract with
* this changes will never get deployed. HorizonStaking is taking it's place.
*/
function getAllocationData(
address _allocationID
) external view returns (bool, address, bytes32, uint256, uint256, uint256);
/**
* @dev New function to get the allocation active status for the rewards manager
* @dev Note that this is only to make tests pass, as the staking contract with
* this changes will never get deployed. HorizonStaking is taking it's place.
*/
function isActiveAllocation(address _allocationID) external view returns (bool);
/**
* @notice Return the current state of an allocation
* @param _allocationID Allocation identifier
* @return AllocationState enum with the state of the allocation
*/
function getAllocationState(address _allocationID) external view returns (AllocationState);
/**
* @notice Return if allocationID is used.
* @param _allocationID Address used as signer by the indexer for an allocation
* @return True if allocationID already used
*/
function isAllocation(address _allocationID) external view returns (bool);
/**
* @notice Return the total amount of tokens allocated to subgraph.
* @param _subgraphDeploymentID Deployment ID for the subgraph
* @return Total tokens allocated to subgraph
*/
function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentID) external view returns (uint256);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.12 <0.8.0 || 0.8.27;
/**
* @title Staking Data interface
* @dev This interface defines some structures used by the Staking contract.
*/
interface IStakingData {
/**
* @dev Allocate GRT tokens for the purpose of serving queries of a subgraph deployment
* An allocation is created in the allocate() function and closed in closeAllocation()
*/
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 __DEPRECATED_effectiveAllocation; // solhint-disable-line var-name-mixedcase
uint256 accRewardsPerAllocatedToken; // Snapshot used for reward calc
uint256 distributedRebates; // Collected rebates that have been rebated
}
// -- Delegation Data --
/**
* @dev Delegation pool information. One per indexer.
*/
struct DelegationPool {
uint32 __DEPRECATED_cooldownBlocks; // solhint-disable-line var-name-mixedcase
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; // Epoch when locked tokens can be withdrawn
}
/**
* @dev Rebates parameters. Used to avoid stack too deep errors in Staking initialize function.
*/
struct RebatesParameters {
uint32 alphaNumerator;
uint32 alphaDenominator;
uint32 lambdaNumerator;
uint32 lambdaDenominator;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.12 <0.8.0 || 0.8.27;
pragma abicoder v2;
import { IStakingData } from "./IStakingData.sol";
import { IStakes } from "./libs/IStakes.sol";
/**
* @title Interface for the StakingExtension contract
* @dev This interface defines the events and functions implemented
* in the StakingExtension contract, which is used to extend the functionality
* of the Staking contract while keeping it within the 24kB mainnet size limit.
* In particular, this interface includes delegation functions and various storage
* getters.
*/
interface IStakingExtension is IStakingData {
/**
* @dev DelegationPool struct as returned by delegationPools(), since
* the original DelegationPool in IStakingData.sol contains a nested mapping.
*/
struct DelegationPoolReturn {
uint32 __DEPRECATED_cooldownBlocks; // solhint-disable-line var-name-mixedcase
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
}
/**
* @dev Emitted when `delegator` delegated `tokens` to the `indexer`, the delegator
* gets `shares` for the delegation pool proportionally to the tokens staked.
*/
event StakeDelegated(address indexed indexer, address indexed delegator, uint256 tokens, uint256 shares);
/**
* @dev Emitted when `delegator` undelegated `tokens` from `indexer`.
* Tokens get locked for withdrawal after a period of time.
*/
event StakeDelegatedLocked(
address indexed indexer,
address indexed delegator,
uint256 tokens,
uint256 shares,
uint256 until
);
/**
* @dev Emitted when `delegator` withdrew delegated `tokens` from `indexer`.
*/
event StakeDelegatedWithdrawn(address indexed indexer, address indexed delegator, uint256 tokens);
/**
* @dev Emitted when `indexer` was slashed for a total of `tokens` amount.
* Tracks `reward` amount of tokens given to `beneficiary`.
*/
event StakeSlashed(address indexed indexer, uint256 tokens, uint256 reward, address beneficiary);
/**
* @dev Emitted when `caller` set `slasher` address as `allowed` to slash stakes.
*/
event SlasherUpdate(address indexed caller, address indexed slasher, bool allowed);
/**
* @notice Set the delegation ratio.
* If set to 10 it means the indexer can use up to 10x the indexer staked amount
* from their delegated tokens
* @dev This function is only callable by the governor
* @param _delegationRatio Delegation capacity multiplier
*/
function setDelegationRatio(uint32 _delegationRatio) external;
/**
* @notice Set the time, in epochs, a Delegator needs to wait to withdraw tokens after undelegating.
* @dev This function is only callable by the governor
* @param _delegationUnbondingPeriod Period in epochs to wait for token withdrawals after undelegating
*/
function setDelegationUnbondingPeriod(uint32 _delegationUnbondingPeriod) external;
/**
* @notice Set a delegation tax percentage to burn when delegated funds are deposited.
* @dev This function is only callable by the governor
* @param _percentage Percentage of delegated tokens to burn as delegation tax, expressed in parts per million
*/
function setDelegationTaxPercentage(uint32 _percentage) external;
/**
* @notice Set or unset an address as allowed slasher.
* @dev This function can only be called by the governor.
* @param _slasher Address of the party allowed to slash indexers
* @param _allowed True if slasher is allowed
*/
function setSlasher(address _slasher, bool _allowed) external;
/**
* @notice Delegate tokens to an indexer.
* @param _indexer Address of the indexer to which tokens are delegated
* @param _tokens Amount of tokens to delegate
* @return Amount of shares issued from the delegation pool
*/
function delegate(address _indexer, uint256 _tokens) external returns (uint256);
/**
* @notice Undelegate tokens from an indexer. Tokens will be locked for the unbonding period.
* @param _indexer Address of the indexer to which tokens had been delegated
* @param _shares Amount of shares to return and undelegate tokens
* @return Amount of tokens returned for the shares of the delegation pool
*/
function undelegate(address _indexer, uint256 _shares) external returns (uint256);
/**
* @notice Withdraw undelegated tokens once the unbonding period has passed, and optionally
* re-delegate to a new indexer.
* @param _indexer Withdraw available tokens delegated to indexer
* @param _newIndexer Re-delegate to indexer address if non-zero, withdraw if zero address
*/
function withdrawDelegated(address _indexer, address _newIndexer) external returns (uint256);
/**
* @notice Slash the indexer stake. Delegated tokens are not subject to slashing.
* @dev Can only be called by the slasher role.
* @param _indexer Address of indexer to slash
* @param _tokens Amount of tokens to slash from the indexer stake
* @param _reward Amount of reward tokens to send to a beneficiary
* @param _beneficiary Address of a beneficiary to receive a reward for the slashing
*/
function slash(address _indexer, uint256 _tokens, uint256 _reward, address _beneficiary) external;
/**
* @notice Return the delegation from a delegator to an indexer.
* @param _indexer Address of the indexer where funds have been delegated
* @param _delegator Address of the delegator
* @return Delegation data
*/
function getDelegation(address _indexer, address _delegator) external view returns (Delegation memory);
/**
* @notice Return whether the delegator has delegated to the indexer.
* @param _indexer Address of the indexer where funds have been delegated
* @param _delegator Address of the delegator
* @return True if delegator has tokens delegated to the indexer
*/
function isDelegator(address _indexer, address _delegator) external view returns (bool);
/**
* @notice Returns amount of delegated tokens ready to be withdrawn after unbonding period.
* @param _delegation Delegation of tokens from delegator to indexer
* @return Amount of tokens to withdraw
*/
function getWithdraweableDelegatedTokens(Delegation memory _delegation) external view returns (uint256);
/**
* @notice Getter for the delegationRatio, i.e. the delegation capacity multiplier:
* If delegation ratio is 100, and an Indexer has staked 5 GRT,
* then they can use up to 500 GRT from the delegated stake
* @return Delegation ratio
*/
function delegationRatio() external view returns (uint32);
/**
* @notice Getter for delegationUnbondingPeriod:
* Time in epochs a delegator needs to wait to withdraw delegated stake
* @return Delegation unbonding period in epochs
*/
function delegationUnbondingPeriod() external view returns (uint32);
/**
* @notice Getter for delegationTaxPercentage:
* Percentage of tokens to tax a delegation deposit, expressed in parts per million
* @return Delegation tax percentage in parts per million
*/
function delegationTaxPercentage() external view returns (uint32);
/**
* @notice Getter for delegationPools[_indexer]:
* gets the delegation pool structure for a particular indexer.
* @param _indexer Address of the indexer for which to query the delegation pool
* @return Delegation pool as a DelegationPoolReturn struct
*/
function delegationPools(address _indexer) external view returns (DelegationPoolReturn memory);
/**
* @notice Getter for operatorAuth[_indexer][_maybeOperator]:
* returns true if the operator is authorized to operate on behalf of the indexer.
* @param _indexer The indexer address for which to query authorization
* @param _maybeOperator The address that may or may not be an operator
* @return True if the operator is authorized to operate on behalf of the indexer
*/
function operatorAuth(address _indexer, address _maybeOperator) external view returns (bool);
/**
* @notice Getter for rewardsDestination[_indexer]:
* returns the address where the indexer's rewards are sent.
* @param _indexer The indexer address for which to query the rewards destination
* @return The address where the indexer's rewards are sent, zero if none is set in which case rewards are re-staked
*/
function rewardsDestination(address _indexer) external view returns (address);
/**
* @notice Getter for subgraphAllocations[_subgraphDeploymentId]:
* returns the amount of tokens allocated to a subgraph deployment.
* @param _subgraphDeploymentId The subgraph deployment for which to query the allocations
* @return The amount of tokens allocated to the subgraph deployment
*/
function subgraphAllocations(bytes32 _subgraphDeploymentId) external view returns (uint256);
/**
* @notice Getter for slashers[_maybeSlasher]:
* returns true if the address is a slasher, i.e. an entity that can slash indexers
* @param _maybeSlasher Address for which to check the slasher role
* @return True if the address is a slasher
*/
function slashers(address _maybeSlasher) external view returns (bool);
/**
* @notice Getter for minimumIndexerStake: the minimum
* amount of GRT that an indexer needs to stake.
* @return Minimum indexer stake in GRT
*/
function minimumIndexerStake() external view returns (uint256);
/**
* @notice Getter for thawingPeriod: the time in blocks an
* indexer needs to wait to unstake tokens.
* @return Thawing period in blocks
*/
function thawingPeriod() external view returns (uint32);
/**
* @notice Getter for curationPercentage: the percentage of
* query fees that are distributed to curators.
* @return Curation percentage in parts per million
*/
function curationPercentage() external view returns (uint32);
/**
* @notice Getter for protocolPercentage: the percentage of
* query fees that are burned as protocol fees.
* @return Protocol percentage in parts per million
*/
function protocolPercentage() external view returns (uint32);
/**
* @notice Getter for maxAllocationEpochs: the maximum time in epochs
* that an allocation can be open before anyone is allowed to close it. This
* also caps the effective allocation when sending the allocation's query fees
* to the rebate pool.
* @return Maximum allocation period in epochs
*/
function maxAllocationEpochs() external view returns (uint32);
/**
* @notice Getter for the numerator of the rebates alpha parameter
* @return Alpha numerator
*/
function alphaNumerator() external view returns (uint32);
/**
* @notice Getter for the denominator of the rebates alpha parameter
* @return Alpha denominator
*/
function alphaDenominator() external view returns (uint32);
/**
* @notice Getter for the numerator of the rebates lambda parameter
* @return Lambda numerator
*/
function lambdaNumerator() external view returns (uint32);
/**
* @notice Getter for the denominator of the rebates lambda parameter
* @return Lambda denominator
*/
function lambdaDenominator() external view returns (uint32);
/**
* @notice Getter for stakes[_indexer]:
* gets the stake information for an indexer as a IStakes.Indexer struct.
* @param _indexer Indexer address for which to query the stake information
* @return Stake information for the specified indexer, as a IStakes.Indexer struct
*/
function stakes(address _indexer) external view returns (IStakes.Indexer memory);
/**
* @notice Getter for allocations[_allocationID]:
* gets an allocation's information as an IStakingData.Allocation struct.
* @param _allocationID Allocation ID for which to query the allocation information
* @return The specified allocation, as an IStakingData.Allocation struct
*/
function allocations(address _allocationID) external view returns (IStakingData.Allocation memory);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
pragma abicoder v2;
interface IStakes {
struct Indexer {
uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer)
uint256 tokensAllocated; // Tokens used in allocations
uint256 tokensLocked; // Tokens locked for withdrawal subject to thawing period
uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6;
import "@openzeppelin/contracts/math/SafeMath.sol";
/**
* @title MathUtils Library
* @notice A collection of functions to perform math operations
*/
library MathUtils {
using SafeMath for uint256;
/**
* @dev Calculates the weighted average of two values pondering each of these
* values based on configured weights. The contribution of each value N is
* weightN/(weightA + weightB). The calculation rounds up to ensure the result
* is always greater than the smallest of the two values.
* @param valueA The amount for value A
* @param weightA The weight to use for value A
* @param valueB The amount for value B
* @param weightB The weight to use for value B
*/
function weightedAverageRoundingUp(
uint256 valueA,
uint256 weightA,
uint256 valueB,
uint256 weightB
) internal pure returns (uint256) {
return valueA.mul(weightA).add(valueB.mul(weightB)).add(weightA.add(weightB).sub(1)).div(weightA.add(weightB));
}
/**
* @dev Returns the minimum of two numbers.
*/
function min(uint256 x, uint256 y) internal pure returns (uint256) {
return x <= y ? x : y;
}
/**
* @dev Returns the difference between two numbers or zero if negative.
*/
function diffOrZero(uint256 x, uint256 y) internal pure returns (uint256) {
return (x > y) ? x.sub(y) : 0;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IGraphToken is IERC20 {
// -- Mint and Burn --
function burn(uint256 amount) external;
function burnFrom(address _from, 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;
// -- Allowance --
function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
import { IGraphProxy } from "./IGraphProxy.sol";
/**
* @title Graph Upgradeable
* @dev This contract is intended to be inherited from upgradeable contracts.
*/
abstract 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(), "Only implementation");
_;
}
/**
* @dev Returns the current implementation.
* @return impl Address of the current implementation
*/
function _implementation() internal view returns (address impl) {
bytes32 slot = IMPLEMENTATION_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
impl := sload(slot)
}
}
/**
* @notice Accept to be an implementation of proxy.
* @param _proxy Proxy to accept
*/
function acceptProxy(IGraphProxy _proxy) external onlyProxyAdmin(_proxy) {
_proxy.acceptUpgrade();
}
/**
* @notice 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.
* @param _proxy Proxy to accept
* @param _data Calldata for the initialization function call (including selector)
*/
function acceptProxyAndCall(IGraphProxy _proxy, bytes calldata _data) external onlyProxyAdmin(_proxy) {
_proxy.acceptUpgradeAndCall(_data);
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.6 || 0.8.27;
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;
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"nameHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"}],"name":"ContractSynced","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":"amount","type":"uint256"}],"name":"HorizonRewardsAssigned","type":"event"},{"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"}],"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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldSubgraphService","type":"address"},{"indexed":true,"internalType":"address","name":"newSubgraphService","type":"address"}],"name":"SubgraphServiceSet","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":"uint256","name":"_tokens","type":"uint256"},{"internalType":"uint256","name":"_accRewardsPerAllocatedToken","type":"uint256"}],"name":"calcRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","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":"_rewardsIssuer","type":"address"},{"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"}],"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":"issuancePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumSubgraphSignal","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":"uint256","name":"_issuancePerBlock","type":"uint256"}],"name":"setIssuancePerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimumSubgraphSignal","type":"uint256"}],"name":"setMinimumSubgraphSignal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_subgraphAvailabilityOracle","type":"address"}],"name":"setSubgraphAvailabilityOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_subgraphService","type":"address"}],"name":"setSubgraphService","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subgraphAvailabilityOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"subgraphService","outputs":[{"internalType":"contract IRewardsIssuer","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":[],"name":"syncAllContracts","outputs":[],"stateMutability":"nonpayable","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"}]Contract Creation Code
6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051611ca761017360003980610e60525080610e37525080610e0e52806117d9525080610de5528061155c525080610dbc525080610d93525080610d6a52806113a05250611ca76000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806393a90a1e11610104578063c8a5f81e116100a2578063e284f84811610071578063e284f848146103ad578063e820e284146103b5578063eeac3e0e146103d5578063f77c4791146103e8576101da565b8063c8a5f81e14610377578063d6866ea51461038a578063db75092614610392578063e242cf1e146103a5576101da565b8063a8cc0ee2116100de578063a8cc0ee21461034c578063b951acd714610354578063c4d66de81461035c578063c7d1117d1461036f576101da565b806393a90a1e146103135780639ce7abe514610326578063a2594d8214610339576101da565b80634986594f1161017c578063702a280e1161014b578063702a280e146102c4578063779bcb9b146102e55780639006ce8b146102f857806392eefe9b14610300576101da565b80634986594f146102735780634bbfc1c5146102965780635c6cbd59146102a95780636c080f18146102bc576101da565b80631324a506116101b85780631324a5061461022557806316a84ab2146102385780631d1c2fec14610258578063260582491461026b576101da565b806305bb8c6b146101df5780630903c094146101fd5780631156bdc114610212575b600080fd5b6101e76103f0565b6040516101f49190611a57565b60405180910390f35b61021061020b366004611895565b6103ff565b005b610210610220366004611962565b61045b565b61021061023336600461197a565b61046f565b61024b610246366004611962565b6104b0565b6040516101f49190611a8f565b61024b610266366004611962565b6104c2565b6101e76104fb565b610286610281366004611962565b61050a565b6040516101f49493929190611c12565b6102106102a4366004611962565b610531565b61024b6102b7366004611962565b61062d565b61024b61071e565b6102d76102d2366004611962565b610724565b6040516101f4929190611c04565b61024b6102f33660046118cd565b610898565b61024b6109be565b61021061030e366004611895565b6109c4565b610210610321366004611895565b6109d5565b61021061033436600461199e565b610a2f565b610210610347366004611895565b610b85565b61024b610ca0565b61024b610cbc565b61021061036a366004611895565b610cc2565b61024b610d2e565b61024b610385366004611a36565b610d46565b610210610d65565b61024b6103a0366004611895565b610e86565b61024b6110bc565b61024b6110c2565b6103c86103c3366004611962565b6111d1565b6040516101f49190611a84565b61024b6103e3366004611962565b6111e5565b6101e7611217565b600f546001600160a01b031681565b610407611226565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061045090611a98565b60405180910390a150565b610463611226565b61046c816112fa565b50565b600f546001600160a01b031633146104a25760405162461bcd60e51b815260040161049990611acf565b60405180910390fd5b6104ac8282611336565b5050565b60116020526000908152604090205481565b60006104cc610d2e565b5060008281526010602052604090206104e48361062d565b808255600d5460029092019190915590505b919050565b6015546001600160a01b031681565b60106020526000908152604090208054600182015460028301546003909301549192909184565b600f546001600160a01b03163314806105de575060008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561059157600080fd5b505afa1580156105a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c991906118b1565b6001600160a01b0316336001600160a01b0316145b6105fa5760405162461bcd60e51b815260040161049990611bdc565b60128190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061045090611b1e565b600081815260106020526040812081610644611399565b6001600160a01b03166346e855da856040518263ffffffff1660e01b815260040161066f9190611a8f565b60206040518083038186803b15801561068757600080fd5b505afa15801561069b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bf9190611a1e565b905060006012548210156106d4576000610706565b610706670de0b6b3a7640000610700846106fa87600201546106f4610ca0565b906113c4565b90611421565b9061147a565b835490915061071590826114e1565b95945050505050565b60145481565b600081815260106020526040812081908161073e8561062d565b9050600061075082846001015461153b565b90506000806040518060400160405280610768611555565b6001600160a01b03908116825260155416602090910152905060005b600281101561084757600082826002811061079b57fe5b60200201516001600160a01b03161461083f578181600281106107ba57fe5b60200201516001600160a01b031663e2e1e8e98a6040518263ffffffff1660e01b81526004016107ea9190611a8f565b60206040518083038186803b15801561080257600080fd5b505afa158015610816573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083a9190611a1e565b830192505b600101610784565b508161085e57600084965096505050505050610893565b60006108768361070086670de0b6b3a7640000611421565b600387015490915061088890826114e1565b975093955050505050505b915091565b60006108a2611555565b6001600160a01b0316836001600160a01b031614806108ce57506015546001600160a01b038481169116145b6108ea5760405162461bcd60e51b815260040161049990611b77565b6000806000806000876001600160a01b03166355c85269886040518263ffffffff1660e01b815260040161091e9190611a57565b60c06040518083038186803b15801561093657600080fd5b505afa15801561094a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096e9190611905565b95509550955095505094508461098c576000955050505050506109b8565b600061099785610724565b5090506109af6109a8858584611580565b83906114e1565b96505050505050505b92915050565b600e5481565b6109cc6115a5565b61046c81611604565b6109dd611226565b601580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede90600090a35050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610a6b57600080fd5b505af1158015610a7f573d6000803e3d6000fd5b505050506040513d6020811015610a9557600080fd5b50516001600160a01b03163314610af3576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610b6757600080fd5b505af1158015610b7b573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bc157600080fd5b505af1158015610bd5573d6000803e3d6000fd5b505050506040513d6020811015610beb57600080fd5b50516001600160a01b03163314610c49576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610c8457600080fd5b505af1158015610c98573d6000803e3d6000fd5b505050505050565b6000610cb6610cad6110c2565b600d54906114e1565b90505b90565b60125481565b610cca6116ac565b6001600160a01b0316336001600160a01b031614610d25576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b61046c816109cc565b6000610d38610ca0565b600d81905543600e55905090565b6000610d5e670de0b6b3a76400006107008486611421565b9392505050565b610d8e7f00000000000000000000000000000000000000000000000000000000000000006116d1565b610db77f00000000000000000000000000000000000000000000000000000000000000006116d1565b610de07f00000000000000000000000000000000000000000000000000000000000000006116d1565b610e097f00000000000000000000000000000000000000000000000000000000000000006116d1565b610e327f00000000000000000000000000000000000000000000000000000000000000006116d1565b610e5b7f00000000000000000000000000000000000000000000000000000000000000006116d1565b610e847f00000000000000000000000000000000000000000000000000000000000000006116d1565b565b600033610e91611555565b6001600160a01b0316816001600160a01b03161480610ebd57506015546001600160a01b038281169116145b610ed95760405162461bcd60e51b815260040161049990611ba5565b600080600080600080866001600160a01b03166355c852698a6040518263ffffffff1660e01b8152600401610f0e9190611a57565b60c06040518083038186803b158015610f2657600080fd5b505afa158015610f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5e9190611905565b9550955095509550955095506000610f75856111e5565b9050610f80856111d1565b15610fd657896001600160a01b0316866001600160a01b03167f9b1323a10f3955b1c9c054ffbda78edfdf49998aaf37f61d9f84776b59ac804360405160405180910390a36000985050505050505050506104f6565b6000871561106357610ff3610fec868685611580565b84906114e1565b90508015611063576110036117d2565b6001600160a01b03166340c10f198a836040518363ffffffff1660e01b8152600401611030929190611a6b565b600060405180830381600087803b15801561104a57600080fd5b505af115801561105e573d6000803e3d6000fd5b505050505b8a6001600160a01b0316876001600160a01b03167fa111914d7f2ea8beca61d12f1a1f38c5533de5f1823c3936422df4404ac2ec68836040516110a69190611a8f565b60405180910390a39a9950505050505050505050565b600d5481565b6000806110da600e54436113c490919063ffffffff16565b9050806110eb576000915050610cb9565b6014546110fc576000915050610cb9565b60006111066117d2565b90506000816001600160a01b03166370a08231611121611399565b6040518263ffffffff1660e01b815260040161113d9190611a57565b60206040518083038186803b15801561115557600080fd5b505afa158015611169573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118d9190611a1e565b9050806111a05760009350505050610cb9565b6014546000906111b09085611421565b90506111c88261070083670de0b6b3a7640000611421565b94505050505090565b600090815260116020526040902054151590565b600081815260106020526040812081806111fe85610724565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561127257600080fd5b505afa158015611286573d6000803e3d6000fd5b505050506040513d602081101561129c57600080fd5b50516001600160a01b03163314610e84576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b611302610d2e565b5060148190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061045090611b4d565b600081611344576000611346565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a9061138c908490611a8f565b60405180910390a2505050565b6000610cb67f00000000000000000000000000000000000000000000000000000000000000006117f9565b60008282111561141b576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600082611430575060006109b8565b8282028284828161143d57fe5b0414610d5e5760405162461bcd60e51b8152600401808060200182810382526021815260200180611c516021913960400191505060405180910390fd5b60008082116114d0576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b8183816114d957fe5b049392505050565b600082820183811015610d5e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600081831161154b576000610d5e565b610d5e83836113c4565b6000610cb67f00000000000000000000000000000000000000000000000000000000000000006117f9565b60008061158d83856113c4565b9050610715670de0b6b3a76400006107008388611421565b6000546001600160a01b03163314610e84576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116611658576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561171e57600080fd5b505afa158015611732573d6000803e3d6000fd5b505050506040513d602081101561174857600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146104ac5760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000610cb67f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b0316806109b85760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561186257600080fd5b505afa158015611876573d6000803e3d6000fd5b505050506040513d602081101561188c57600080fd5b50519392505050565b6000602082840312156118a6578081fd5b8135610d5e81611c2d565b6000602082840312156118c2578081fd5b8151610d5e81611c2d565b600080604083850312156118df578081fd5b82356118ea81611c2d565b915060208301356118fa81611c2d565b809150509250929050565b60008060008060008060c0878903121561191d578182fd5b865161192881611c42565b602088015190965061193981611c2d565b6040880151606089015160808a015160a0909a0151989b929a5090989097909650945092505050565b600060208284031215611973578081fd5b5035919050565b6000806040838503121561198c578182fd5b8235915060208301356118fa81611c42565b6000806000604084860312156119b2578283fd5b83356119bd81611c2d565b9250602084013567ffffffffffffffff808211156119d9578384fd5b818601915086601f8301126119ec578384fd5b8135818111156119fa578485fd5b876020828501011115611a0b578485fd5b6020830194508093505050509250925092565b600060208284031215611a2f578081fd5b5051919050565b60008060408385031215611a48578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252601590820152741b5a5b9a5b5d5b54dd5899dc985c1a14da59db985b605a1b604082015260600190565b60208082526010908201526f69737375616e6365506572426c6f636b60801b604082015260600190565b6020808252601490820152732737ba1030903932bbb0b932399034b9b9bab2b960611b604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206120726577617264732069737375657200604082015260600190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461046c57600080fd5b801515811461046c57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220c1c7249959ec03bd119b3d15c338a6e323ecd6c699ef1058d9b729494ed7889664736f6c63430007060033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806393a90a1e11610104578063c8a5f81e116100a2578063e284f84811610071578063e284f848146103ad578063e820e284146103b5578063eeac3e0e146103d5578063f77c4791146103e8576101da565b8063c8a5f81e14610377578063d6866ea51461038a578063db75092614610392578063e242cf1e146103a5576101da565b8063a8cc0ee2116100de578063a8cc0ee21461034c578063b951acd714610354578063c4d66de81461035c578063c7d1117d1461036f576101da565b806393a90a1e146103135780639ce7abe514610326578063a2594d8214610339576101da565b80634986594f1161017c578063702a280e1161014b578063702a280e146102c4578063779bcb9b146102e55780639006ce8b146102f857806392eefe9b14610300576101da565b80634986594f146102735780634bbfc1c5146102965780635c6cbd59146102a95780636c080f18146102bc576101da565b80631324a506116101b85780631324a5061461022557806316a84ab2146102385780631d1c2fec14610258578063260582491461026b576101da565b806305bb8c6b146101df5780630903c094146101fd5780631156bdc114610212575b600080fd5b6101e76103f0565b6040516101f49190611a57565b60405180910390f35b61021061020b366004611895565b6103ff565b005b610210610220366004611962565b61045b565b61021061023336600461197a565b61046f565b61024b610246366004611962565b6104b0565b6040516101f49190611a8f565b61024b610266366004611962565b6104c2565b6101e76104fb565b610286610281366004611962565b61050a565b6040516101f49493929190611c12565b6102106102a4366004611962565b610531565b61024b6102b7366004611962565b61062d565b61024b61071e565b6102d76102d2366004611962565b610724565b6040516101f4929190611c04565b61024b6102f33660046118cd565b610898565b61024b6109be565b61021061030e366004611895565b6109c4565b610210610321366004611895565b6109d5565b61021061033436600461199e565b610a2f565b610210610347366004611895565b610b85565b61024b610ca0565b61024b610cbc565b61021061036a366004611895565b610cc2565b61024b610d2e565b61024b610385366004611a36565b610d46565b610210610d65565b61024b6103a0366004611895565b610e86565b61024b6110bc565b61024b6110c2565b6103c86103c3366004611962565b6111d1565b6040516101f49190611a84565b61024b6103e3366004611962565b6111e5565b6101e7611217565b600f546001600160a01b031681565b610407611226565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061045090611a98565b60405180910390a150565b610463611226565b61046c816112fa565b50565b600f546001600160a01b031633146104a25760405162461bcd60e51b815260040161049990611acf565b60405180910390fd5b6104ac8282611336565b5050565b60116020526000908152604090205481565b60006104cc610d2e565b5060008281526010602052604090206104e48361062d565b808255600d5460029092019190915590505b919050565b6015546001600160a01b031681565b60106020526000908152604090208054600182015460028301546003909301549192909184565b600f546001600160a01b03163314806105de575060008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561059157600080fd5b505afa1580156105a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c991906118b1565b6001600160a01b0316336001600160a01b0316145b6105fa5760405162461bcd60e51b815260040161049990611bdc565b60128190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061045090611b1e565b600081815260106020526040812081610644611399565b6001600160a01b03166346e855da856040518263ffffffff1660e01b815260040161066f9190611a8f565b60206040518083038186803b15801561068757600080fd5b505afa15801561069b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bf9190611a1e565b905060006012548210156106d4576000610706565b610706670de0b6b3a7640000610700846106fa87600201546106f4610ca0565b906113c4565b90611421565b9061147a565b835490915061071590826114e1565b95945050505050565b60145481565b600081815260106020526040812081908161073e8561062d565b9050600061075082846001015461153b565b90506000806040518060400160405280610768611555565b6001600160a01b03908116825260155416602090910152905060005b600281101561084757600082826002811061079b57fe5b60200201516001600160a01b03161461083f578181600281106107ba57fe5b60200201516001600160a01b031663e2e1e8e98a6040518263ffffffff1660e01b81526004016107ea9190611a8f565b60206040518083038186803b15801561080257600080fd5b505afa158015610816573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083a9190611a1e565b830192505b600101610784565b508161085e57600084965096505050505050610893565b60006108768361070086670de0b6b3a7640000611421565b600387015490915061088890826114e1565b975093955050505050505b915091565b60006108a2611555565b6001600160a01b0316836001600160a01b031614806108ce57506015546001600160a01b038481169116145b6108ea5760405162461bcd60e51b815260040161049990611b77565b6000806000806000876001600160a01b03166355c85269886040518263ffffffff1660e01b815260040161091e9190611a57565b60c06040518083038186803b15801561093657600080fd5b505afa15801561094a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096e9190611905565b95509550955095505094508461098c576000955050505050506109b8565b600061099785610724565b5090506109af6109a8858584611580565b83906114e1565b96505050505050505b92915050565b600e5481565b6109cc6115a5565b61046c81611604565b6109dd611226565b601580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede90600090a35050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610a6b57600080fd5b505af1158015610a7f573d6000803e3d6000fd5b505050506040513d6020811015610a9557600080fd5b50516001600160a01b03163314610af3576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610b6757600080fd5b505af1158015610b7b573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bc157600080fd5b505af1158015610bd5573d6000803e3d6000fd5b505050506040513d6020811015610beb57600080fd5b50516001600160a01b03163314610c49576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610c8457600080fd5b505af1158015610c98573d6000803e3d6000fd5b505050505050565b6000610cb6610cad6110c2565b600d54906114e1565b90505b90565b60125481565b610cca6116ac565b6001600160a01b0316336001600160a01b031614610d25576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b61046c816109cc565b6000610d38610ca0565b600d81905543600e55905090565b6000610d5e670de0b6b3a76400006107008486611421565b9392505050565b610d8e7fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6116d1565b610db77fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f670636116d1565b610de07f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c531807616116d1565b610e097f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d1670346116d1565b610e327f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc192476116d1565b610e5b7fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf06116d1565b610e847f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36116d1565b565b600033610e91611555565b6001600160a01b0316816001600160a01b03161480610ebd57506015546001600160a01b038281169116145b610ed95760405162461bcd60e51b815260040161049990611ba5565b600080600080600080866001600160a01b03166355c852698a6040518263ffffffff1660e01b8152600401610f0e9190611a57565b60c06040518083038186803b158015610f2657600080fd5b505afa158015610f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5e9190611905565b9550955095509550955095506000610f75856111e5565b9050610f80856111d1565b15610fd657896001600160a01b0316866001600160a01b03167f9b1323a10f3955b1c9c054ffbda78edfdf49998aaf37f61d9f84776b59ac804360405160405180910390a36000985050505050505050506104f6565b6000871561106357610ff3610fec868685611580565b84906114e1565b90508015611063576110036117d2565b6001600160a01b03166340c10f198a836040518363ffffffff1660e01b8152600401611030929190611a6b565b600060405180830381600087803b15801561104a57600080fd5b505af115801561105e573d6000803e3d6000fd5b505050505b8a6001600160a01b0316876001600160a01b03167fa111914d7f2ea8beca61d12f1a1f38c5533de5f1823c3936422df4404ac2ec68836040516110a69190611a8f565b60405180910390a39a9950505050505050505050565b600d5481565b6000806110da600e54436113c490919063ffffffff16565b9050806110eb576000915050610cb9565b6014546110fc576000915050610cb9565b60006111066117d2565b90506000816001600160a01b03166370a08231611121611399565b6040518263ffffffff1660e01b815260040161113d9190611a57565b60206040518083038186803b15801561115557600080fd5b505afa158015611169573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118d9190611a1e565b9050806111a05760009350505050610cb9565b6014546000906111b09085611421565b90506111c88261070083670de0b6b3a7640000611421565b94505050505090565b600090815260116020526040902054151590565b600081815260106020526040812081806111fe85610724565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561127257600080fd5b505afa158015611286573d6000803e3d6000fd5b505050506040513d602081101561129c57600080fd5b50516001600160a01b03163314610e84576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b611302610d2e565b5060148190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061045090611b4d565b600081611344576000611346565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a9061138c908490611a8f565b60405180910390a2505050565b6000610cb67fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6117f9565b60008282111561141b576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600082611430575060006109b8565b8282028284828161143d57fe5b0414610d5e5760405162461bcd60e51b8152600401808060200182810382526021815260200180611c516021913960400191505060405180910390fd5b60008082116114d0576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b8183816114d957fe5b049392505050565b600082820183811015610d5e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600081831161154b576000610d5e565b610d5e83836113c4565b6000610cb67f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d1670346117f9565b60008061158d83856113c4565b9050610715670de0b6b3a76400006107008388611421565b6000546001600160a01b03163314610e84576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116611658576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561171e57600080fd5b505afa158015611732573d6000803e3d6000fd5b505050506040513d602081101561174857600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146104ac5760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000610cb67f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc192475b6000818152600160205260408120546001600160a01b0316806109b85760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561186257600080fd5b505afa158015611876573d6000803e3d6000fd5b505050506040513d602081101561188c57600080fd5b50519392505050565b6000602082840312156118a6578081fd5b8135610d5e81611c2d565b6000602082840312156118c2578081fd5b8151610d5e81611c2d565b600080604083850312156118df578081fd5b82356118ea81611c2d565b915060208301356118fa81611c2d565b809150509250929050565b60008060008060008060c0878903121561191d578182fd5b865161192881611c42565b602088015190965061193981611c2d565b6040880151606089015160808a015160a0909a0151989b929a5090989097909650945092505050565b600060208284031215611973578081fd5b5035919050565b6000806040838503121561198c578182fd5b8235915060208301356118fa81611c42565b6000806000604084860312156119b2578283fd5b83356119bd81611c2d565b9250602084013567ffffffffffffffff808211156119d9578384fd5b818601915086601f8301126119ec578384fd5b8135818111156119fa578485fd5b876020828501011115611a0b578485fd5b6020830194508093505050509250925092565b600060208284031215611a2f578081fd5b5051919050565b60008060408385031215611a48578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252601590820152741b5a5b9a5b5d5b54dd5899dc985c1a14da59db985b605a1b604082015260600190565b60208082526010908201526f69737375616e6365506572426c6f636b60801b604082015260600190565b6020808252601490820152732737ba1030903932bbb0b932399034b9b9bab2b960611b604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206120726577617264732069737375657200604082015260600190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461046c57600080fd5b801515811461046c57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220c1c7249959ec03bd119b3d15c338a6e323ecd6c699ef1058d9b729494ed7889664736f6c63430007060033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.