Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
RewardsManager
Compiler Version
v0.7.4+commit.3f05b770
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/math/SafeMath.sol"; import "../upgrades/GraphUpgradeable.sol"; import "./RewardsManagerStorage.sol"; import "./IRewardsManager.sol"; contract RewardsManager is RewardsManagerV1Storage, GraphUpgradeable, IRewardsManager { using SafeMath for uint256; uint256 private constant TOKEN_DECIMALS = 1e18; uint256 private constant MIN_ISSUANCE_RATE = 1e18; // -- Events -- /** * @dev Emitted when rewards are assigned to an indexer. */ event RewardsAssigned( address indexed indexer, address indexed allocationID, uint256 epoch, uint256 amount ); /** * @dev Emitted when rewards are denied to an indexer. */ event RewardsDenied(address indexed indexer, address indexed allocationID, uint256 epoch); /** * @dev Emitted when a subgraph is denied for claiming rewards. */ event RewardsDenylistUpdated(bytes32 indexed subgraphDeploymentID, uint256 sinceBlock); // -- Modifiers -- modifier onlySubgraphAvailabilityOracle() { require( msg.sender == address(subgraphAvailabilityOracle), "Caller must be the subgraph availability oracle" ); _; } /** * @dev Initialize this contract. */ function initialize(address _controller, uint256 _issuanceRate) external onlyImpl { Managed._initialize(_controller); // Settings _setIssuanceRate(_issuanceRate); } /** * @dev Sets the issuance rate. * The issuance rate is defined as a percentage increase of the total supply per block. * This means that it needs to be greater than 1.0, any number under 1.0 is not * allowed and an issuance rate of 1.0 means no issuance. * To accommodate a high precision the issuance rate is expressed in wei. * @param _issuanceRate Issuance rate expressed in wei */ function setIssuanceRate(uint256 _issuanceRate) external override onlyGovernor { _setIssuanceRate(_issuanceRate); } /** * @dev Sets the issuance rate. * @param _issuanceRate Issuance rate */ function _setIssuanceRate(uint256 _issuanceRate) private { require(_issuanceRate >= MIN_ISSUANCE_RATE, "Issuance rate under minimum allowed"); // Called since `issuance rate` will change updateAccRewardsPerSignal(); issuanceRate = _issuanceRate; emit ParameterUpdated("issuanceRate"); } /** * @dev Sets the subgraph oracle allowed to denegate distribution of rewards to subgraphs. * @param _subgraphAvailabilityOracle Address of the subgraph availability oracle */ function setSubgraphAvailabilityOracle(address _subgraphAvailabilityOracle) external override onlyGovernor { subgraphAvailabilityOracle = _subgraphAvailabilityOracle; emit ParameterUpdated("subgraphAvailabilityOracle"); } /** * @dev Denies to claim rewards for a subgraph. * NOTE: Can only be called by the subgraph availability oracle * @param _subgraphDeploymentID Subgraph deployment ID * @param _deny Whether to set the subgraph as denied for claiming rewards or not */ function setDenied(bytes32 _subgraphDeploymentID, bool _deny) external override onlySubgraphAvailabilityOracle { _setDenied(_subgraphDeploymentID, _deny); } /** * @dev Denies to claim rewards for multiple subgraph. * NOTE: Can only be called by the subgraph availability oracle * @param _subgraphDeploymentID Array of subgraph deployment ID * @param _deny Array of denied status for claiming rewards for each subgraph */ function setDeniedMany(bytes32[] calldata _subgraphDeploymentID, bool[] calldata _deny) external override onlySubgraphAvailabilityOracle { require(_subgraphDeploymentID.length == _deny.length, "!length"); for (uint256 i = 0; i < _subgraphDeploymentID.length; i++) { _setDenied(_subgraphDeploymentID[i], _deny[i]); } } /** * @dev Internal: Denies to claim rewards for a subgraph. * @param _subgraphDeploymentID Subgraph deployment ID * @param _deny Whether to set the subgraph as denied for claiming rewards or not */ function _setDenied(bytes32 _subgraphDeploymentID, bool _deny) private { uint256 sinceBlock = _deny ? block.number : 0; denylist[_subgraphDeploymentID] = sinceBlock; emit RewardsDenylistUpdated(_subgraphDeploymentID, sinceBlock); } /** * @dev Tells if subgraph is in deny list * @param _subgraphDeploymentID Subgraph deployment ID to check */ function isDenied(bytes32 _subgraphDeploymentID) public override view returns (bool) { return denylist[_subgraphDeploymentID] > 0; } /** * @dev Gets the issuance of rewards per signal since last updated. * * Compound interest formula: `a = p(1 + r/n)^nt` * The formula is simplified with `n = 1` as we apply the interest once every time step. * The `r` is passed with +1 included. So for 10% instead of 0.1 it is 1.1 * The simplified formula is `a = p * r^t` * * Notation: * t: time steps are in blocks since last updated * p: total supply of GRT tokens * a: inflated amount of total supply for the period `t` when interest `r` is applied * x: newly accrued rewards token for the period `t` * * @return newly accrued rewards per signal since last update */ function getNewRewardsPerSignal() public override view returns (uint256) { // Calculate time steps uint256 t = block.number.sub(accRewardsPerSignalLastBlockUpdated); // Optimization to skip calculations if zero time steps elapsed if (t == 0) { return 0; } // Zero issuance under a rate of 1.0 if (issuanceRate <= MIN_ISSUANCE_RATE) { return 0; } // Zero issuance if no signalled tokens IGraphToken graphToken = graphToken(); uint256 signalledTokens = graphToken.balanceOf(address(curation())); if (signalledTokens == 0) { return 0; } uint256 r = issuanceRate; uint256 p = graphToken.totalSupply(); uint256 a = p.mul(_pow(r, t, TOKEN_DECIMALS)).div(TOKEN_DECIMALS); // New issuance per signalled token during time steps uint256 x = a.sub(p); // We multiply the decimals to keep the precision as fixed-point number return x.mul(TOKEN_DECIMALS).div(signalledTokens); } /** * @dev Gets the currently accumulated rewards per signal. */ function getAccRewardsPerSignal() public override view returns (uint256) { return accRewardsPerSignal.add(getNewRewardsPerSignal()); } /** * @dev Gets the accumulated rewards for the subgraph. * @param _subgraphDeploymentID Subgraph deployment * @return Accumulated rewards for subgraph */ function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID) public override view returns (uint256) { Subgraph storage subgraph = subgraphs[_subgraphDeploymentID]; uint256 newAccrued = getAccRewardsPerSignal().sub(subgraph.accRewardsPerSignalSnapshot); uint256 subgraphSignalledTokens = curation().getCurationPoolTokens(_subgraphDeploymentID); if (subgraphSignalledTokens == 0) { return 0; } uint256 newValue = newAccrued.mul(subgraphSignalledTokens).div(TOKEN_DECIMALS); return subgraph.accRewardsForSubgraph.add(newValue); } /** * @dev Gets the accumulated rewards per allocated token for the subgraph. * @param _subgraphDeploymentID Subgraph deployment * @return Accumulated rewards per allocated token for the subgraph * @return Accumulated rewards for subgraph */ function getAccRewardsPerAllocatedToken(bytes32 _subgraphDeploymentID) public override view returns (uint256, uint256) { Subgraph storage subgraph = subgraphs[_subgraphDeploymentID]; uint256 accRewardsForSubgraph = getAccRewardsForSubgraph(_subgraphDeploymentID); uint256 newAccrued = accRewardsForSubgraph.sub(subgraph.accRewardsForSubgraphSnapshot); uint256 subgraphAllocatedTokens = staking().getSubgraphAllocatedTokens( _subgraphDeploymentID ); if (subgraphAllocatedTokens == 0) { return (0, accRewardsForSubgraph); } uint256 newValue = newAccrued.mul(TOKEN_DECIMALS).div(subgraphAllocatedTokens); return (subgraph.accRewardsPerAllocatedToken.add(newValue), accRewardsForSubgraph); } /** * @dev Updates the accumulated rewards per signal and save checkpoint block number. * Must be called before `issuanceRate` or `total signalled GRT` changes * Called from the Curation contract on mint() and burn() * @return Accumulated rewards per signal */ function updateAccRewardsPerSignal() public override returns (uint256) { accRewardsPerSignal = getAccRewardsPerSignal(); accRewardsPerSignalLastBlockUpdated = block.number; return accRewardsPerSignal; } /** * @dev Triggers an update of rewards for a subgraph. * Must be called before `signalled GRT` on a subgraph changes. * Note: Hook called from the Curation contract on mint() and burn() * @param _subgraphDeploymentID Subgraph deployment * @return Accumulated rewards for subgraph */ function onSubgraphSignalUpdate(bytes32 _subgraphDeploymentID) external override returns (uint256) { // Called since `total signalled GRT` will change updateAccRewardsPerSignal(); // Updates the accumulated rewards for a subgraph Subgraph storage subgraph = subgraphs[_subgraphDeploymentID]; subgraph.accRewardsForSubgraph = getAccRewardsForSubgraph(_subgraphDeploymentID); subgraph.accRewardsPerSignalSnapshot = accRewardsPerSignal; return subgraph.accRewardsForSubgraph; } /** * @dev Triggers an update of rewards for a subgraph. * Must be called before allocation on a subgraph changes. * NOTE: Hook called from the Staking contract on allocate() and close() * * @param _subgraphDeploymentID Subgraph deployment * @return Accumulated rewards per allocated token for a subgraph */ function onSubgraphAllocationUpdate(bytes32 _subgraphDeploymentID) public override returns (uint256) { Subgraph storage subgraph = subgraphs[_subgraphDeploymentID]; ( uint256 accRewardsPerAllocatedToken, uint256 accRewardsForSubgraph ) = getAccRewardsPerAllocatedToken(_subgraphDeploymentID); subgraph.accRewardsPerAllocatedToken = accRewardsPerAllocatedToken; subgraph.accRewardsForSubgraphSnapshot = accRewardsForSubgraph; return subgraph.accRewardsPerAllocatedToken; } /** * @dev Calculate current rewards for a given allocation on demand. * @param _allocationID Allocation * @return Rewards amount for an allocation */ function getRewards(address _allocationID) external override view returns (uint256) { IStaking.Allocation memory alloc = staking().getAllocation(_allocationID); (uint256 accRewardsPerAllocatedToken, ) = getAccRewardsPerAllocatedToken( alloc.subgraphDeploymentID ); return _calcRewards( alloc.tokens, alloc.accRewardsPerAllocatedToken, accRewardsPerAllocatedToken ); } /** * @dev Calculate current rewards for a given allocation. * @param _tokens Tokens allocated * @param _startAccRewardsPerAllocatedToken Allocation start accumulated rewards * @param _endAccRewardsPerAllocatedToken Allocation end accumulated rewards * @return Rewards amount */ function _calcRewards( uint256 _tokens, uint256 _startAccRewardsPerAllocatedToken, uint256 _endAccRewardsPerAllocatedToken ) private pure returns (uint256) { uint256 newAccrued = _endAccRewardsPerAllocatedToken.sub(_startAccRewardsPerAllocatedToken); return newAccrued.mul(_tokens).div(TOKEN_DECIMALS); } /** * @dev Pull rewards from the contract for a particular allocation. * This function can only be called by the Staking contract. * This function will mint the necessary tokens to reward based on the inflation calculation. * @param _allocationID Allocation * @return Assigned rewards amount */ function takeRewards(address _allocationID) external override returns (uint256) { // Only Staking contract is authorized as caller IStaking staking = staking(); require(msg.sender == address(staking), "Caller must be the staking contract"); IGraphToken graphToken = graphToken(); IStaking.Allocation memory alloc = staking.getAllocation(_allocationID); uint256 accRewardsPerAllocatedToken = onSubgraphAllocationUpdate( alloc.subgraphDeploymentID ); // Do not do rewards on denied subgraph deployments ID if (isDenied(alloc.subgraphDeploymentID)) { emit RewardsDenied(alloc.indexer, _allocationID, alloc.closedAtEpoch); return 0; } // Calculate rewards accrued by this allocation uint256 rewards = _calcRewards( alloc.tokens, alloc.accRewardsPerAllocatedToken, accRewardsPerAllocatedToken ); // Mint directly to staking contract for the reward amount // The staking contract will do bookkeeping of the reward and // assign in proportion to each stakeholder incentive graphToken.mint(address(staking), rewards); emit RewardsAssigned(alloc.indexer, _allocationID, alloc.closedAtEpoch, rewards); return rewards; } /** * @dev Raises x to the power of n with scaling factor of base. * Based on: https://github.com/makerdao/dss/blob/master/src/pot.sol#L81 * @param x Base of the exponentiation * @param n Exponent * @param base Scaling factor * @return z Exponential of n with base x */ function _pow( uint256 x, uint256 n, uint256 base ) private pure returns (uint256 z) { assembly { switch x case 0 { switch n case 0 { z := base } default { z := 0 } } default { switch mod(n, 2) case 0 { z := base } default { z := x } let half := div(base, 2) // for rounding. for { n := div(n, 2) } n { n := div(n, 2) } { let xx := mul(x, x) if iszero(eq(div(xx, x), x)) { revert(0, 0) } let xxRound := add(xx, half) if lt(xxRound, xx) { revert(0, 0) } x := div(xxRound, base) if mod(n, 2) { let zx := mul(z, x) if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0, 0) } let zxRound := add(zx, half) if lt(zxRound, zx) { revert(0, 0) } z := div(zxRound, base) } } } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; import "./IGraphProxy.sol"; /** * @title Graph Upgradeable * @dev This contract is intended to be inherited from upgradeable contracts. */ contract GraphUpgradeable { /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Check if the caller is the proxy admin. */ modifier onlyProxyAdmin(IGraphProxy _proxy) { require(msg.sender == _proxy.admin(), "Caller must be the proxy admin"); _; } /** * @dev Check if the caller is the implementation. */ modifier onlyImpl { require(msg.sender == _implementation(), "Caller must be the implementation"); _; } /** * @dev Returns the current implementation. * @return impl Address of the current implementation */ function _implementation() internal view returns (address impl) { bytes32 slot = IMPLEMENTATION_SLOT; assembly { impl := sload(slot) } } /** * @dev Accept to be an implementation of proxy. */ function acceptProxy(IGraphProxy _proxy) external onlyProxyAdmin(_proxy) { _proxy.acceptUpgrade(); } /** * @dev Accept to be an implementation of proxy and then call a function from the new * implementation as specified by `_data`, which should be an encoded function call. This is * useful to initialize new storage variables in the proxied contract. */ function acceptProxyAndCall(IGraphProxy _proxy, bytes calldata _data) external onlyProxyAdmin(_proxy) { _proxy.acceptUpgradeAndCall(_data); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; import "./IRewardsManager.sol"; import "../governance/Managed.sol"; contract RewardsManagerV1Storage is Managed { // -- State -- uint256 public issuanceRate; uint256 public accRewardsPerSignal; uint256 public accRewardsPerSignalLastBlockUpdated; // Address of role allowed to deny rewards on subgraphs address public subgraphAvailabilityOracle; // Subgraph related rewards: subgraph deployment ID => subgraph rewards mapping(bytes32 => IRewardsManager.Subgraph) public subgraphs; // Subgraph denylist : subgraph deployment ID => block when added or zero (if not denied) mapping(bytes32 => uint256) public denylist; }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; interface IRewardsManager { /** * @dev Stores accumulated rewards and snapshots related to a particular SubgraphDeployment. */ struct Subgraph { uint256 accRewardsForSubgraph; uint256 accRewardsForSubgraphSnapshot; uint256 accRewardsPerSignalSnapshot; uint256 accRewardsPerAllocatedToken; } // -- Params -- function setIssuanceRate(uint256 _issuanceRate) external; // -- Denylist -- function setSubgraphAvailabilityOracle(address _subgraphAvailabilityOracle) external; function setDenied(bytes32 _subgraphDeploymentID, bool _deny) external; function setDeniedMany(bytes32[] calldata _subgraphDeploymentID, bool[] calldata _deny) external; function isDenied(bytes32 _subgraphDeploymentID) external view returns (bool); // -- Getters -- function getNewRewardsPerSignal() external view returns (uint256); function getAccRewardsPerSignal() external view returns (uint256); function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID) external view returns (uint256); function getAccRewardsPerAllocatedToken(bytes32 _subgraphDeploymentID) external view returns (uint256, uint256); function getRewards(address _allocationID) external view returns (uint256); // -- Updates -- function updateAccRewardsPerSignal() external returns (uint256); function takeRewards(address _allocationID) external returns (uint256); // -- Hooks -- function onSubgraphSignalUpdate(bytes32 _subgraphDeploymentID) external returns (uint256); function onSubgraphAllocationUpdate(bytes32 _subgraphDeploymentID) external returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; interface IGraphProxy { function admin() external returns (address); function setAdmin(address _newAdmin) external; function implementation() external returns (address); function pendingImplementation() external returns (address); function upgradeTo(address _newImplementation) external; function acceptUpgrade() external; function acceptUpgradeAndCall(bytes calldata data) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; import "./IManaged.sol"; import "./IController.sol"; import "../curation/ICuration.sol"; import "../epochs/IEpochManager.sol"; import "../rewards/IRewardsManager.sol"; import "../staking/IStaking.sol"; import "../token/IGraphToken.sol"; /** * @title Graph Managed contract * @dev The Managed contract provides an interface for contracts to interact with the Controller * Inspired by Livepeer: * https://github.com/livepeer/protocol/blob/streamflow/contracts/Controller.sol */ contract Managed { // Controller that contract is registered with IController public controller; mapping(bytes32 => address) public addressCache; uint256[10] private __gap; event ParameterUpdated(string param); event SetController(address controller); function _notPartialPaused() internal view { require(!controller.paused(), "Paused"); require(!controller.partialPaused(), "Partial-paused"); } function _notPaused() internal view { require(!controller.paused(), "Paused"); } function _onlyGovernor() internal view { require(msg.sender == controller.getGovernor(), "Caller must be Controller governor"); } modifier notPartialPaused { _notPartialPaused(); _; } modifier notPaused { _notPaused(); _; } // Check if sender is controller modifier onlyController() { require(msg.sender == address(controller), "Caller must be Controller"); _; } modifier onlyGovernor() { _onlyGovernor(); _; } /** * @dev Initialize the controller */ function _initialize(address _controller) internal { _setController(_controller); } /** * @notice Set Controller. Only callable by current controller * @param _controller Controller contract address */ function setController(address _controller) external onlyController { _setController(_controller); } /** * @dev Set controller. * @param _controller Controller contract address */ function _setController(address _controller) internal { require(_controller != address(0), "Controller must be set"); controller = IController(_controller); emit SetController(_controller); } /** * @dev Return Curation interface * @return Curation contract registered with Controller */ function curation() internal view returns (ICuration) { return ICuration(controller.getContractProxy(keccak256("Curation"))); } /** * @dev Return EpochManager interface * @return Epoch manager contract registered with Controller */ function epochManager() internal view returns (IEpochManager) { return IEpochManager(controller.getContractProxy(keccak256("EpochManager"))); } /** * @dev Return RewardsManager interface * @return Rewards manager contract registered with Controller */ function rewardsManager() internal view returns (IRewardsManager) { return IRewardsManager(controller.getContractProxy(keccak256("RewardsManager"))); } /** * @dev Return Staking interface * @return Staking contract registered with Controller */ function staking() internal view returns (IStaking) { return IStaking(controller.getContractProxy(keccak256("Staking"))); } /** * @dev Return GraphToken interface * @return Graph token contract registered with Controller */ function graphToken() internal view returns (IGraphToken) { return IGraphToken(controller.getContractProxy(keccak256("GraphToken"))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; interface IManaged { function setController(address _controller) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12 <0.8.0; interface IController { function getGovernor() external view returns (address); // -- Registry -- function setContractProxy(bytes32 _id, address _contractAddress) external; function unsetContractProxy(bytes32 _id) external; function updateController(bytes32 _id, address _controller) external; function getContractProxy(bytes32 _id) external view returns (address); // -- Pausing -- function setPartialPaused(bool _partialPaused) external; function setPaused(bool _paused) external; function setPauseGuardian(address _newPauseGuardian) external; function paused() external view returns (bool); function partialPaused() external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; import "./IGraphCurationToken.sol"; interface ICuration { // -- Pool -- struct CurationPool { uint256 tokens; // GRT Tokens stored as reserves for the subgraph deployment uint32 reserveRatio; // Ratio for the bonding curve IGraphCurationToken gcs; // Curation token contract for this curation pool } // -- Configuration -- function setDefaultReserveRatio(uint32 _defaultReserveRatio) external; function setMinimumCurationDeposit(uint256 _minimumCurationDeposit) external; function setCurationTaxPercentage(uint32 _percentage) external; // -- Curation -- function mint( bytes32 _subgraphDeploymentID, uint256 _tokensIn, uint256 _signalOutMin ) external returns (uint256, uint256); function burn( bytes32 _subgraphDeploymentID, uint256 _signalIn, uint256 _tokensOutMin ) external returns (uint256); function collect(bytes32 _subgraphDeploymentID, uint256 _tokens) external; // -- Getters -- function isCurated(bytes32 _subgraphDeploymentID) external view returns (bool); function getCuratorSignal(address _curator, bytes32 _subgraphDeploymentID) external view returns (uint256); function getCurationPoolSignal(bytes32 _subgraphDeploymentID) external view returns (uint256); function getCurationPoolTokens(bytes32 _subgraphDeploymentID) external view returns (uint256); function tokensToSignal(bytes32 _subgraphDeploymentID, uint256 _tokensIn) external view returns (uint256, uint256); function signalToTokens(bytes32 _subgraphDeploymentID, uint256 _signalIn) external view returns (uint256); function curationTaxPercentage() external view returns (uint32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; interface IEpochManager { // -- Configuration -- function setEpochLength(uint256 _epochLength) external; // -- Epochs function runEpoch() external; // -- Getters -- function isCurrentEpochRun() external view returns (bool); function blockNum() external view returns (uint256); function blockHash(uint256 _block) external view returns (bytes32); function currentEpoch() external view returns (uint256); function currentEpochBlock() external view returns (uint256); function currentEpochBlockSinceStart() external view returns (uint256); function epochsSince(uint256 _epoch) external view returns (uint256); function epochsSinceUpdate() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12 <0.8.0; pragma experimental ABIEncoderV2; interface IStaking { // -- Allocation Data -- /** * @dev Possible states an allocation can be * States: * - Null = indexer == address(0) * - Active = not Null && tokens > 0 * - Closed = Active && closedAtEpoch != 0 * - Finalized = Closed && closedAtEpoch + channelDisputeEpochs > now() * - Claimed = not Null && tokens == 0 */ enum AllocationState { Null, Active, Closed, Finalized, Claimed } /** * @dev Allocate GRT tokens for the purpose of serving queries of a subgraph deployment * An allocation is created in the allocate() function and consumed in claim() */ struct Allocation { address indexer; bytes32 subgraphDeploymentID; uint256 tokens; // Tokens allocated to a SubgraphDeployment uint256 createdAtEpoch; // Epoch when it was created uint256 closedAtEpoch; // Epoch when it was closed uint256 collectedFees; // Collected fees for the allocation uint256 effectiveAllocation; // Effective allocation when closed uint256 accRewardsPerAllocatedToken; // Snapshot used for reward calc } /** * @dev Represents a request to close an allocation with a specific proof of indexing. * This is passed when calling closeAllocationMany to define the closing parameters for * each allocation. */ struct CloseAllocationRequest { address allocationID; bytes32 poi; } // -- Delegation Data -- /** * @dev Delegation pool information. One per indexer. */ struct DelegationPool { uint32 cooldownBlocks; // Blocks to wait before updating parameters uint32 indexingRewardCut; // in PPM uint32 queryFeeCut; // in PPM uint256 updatedAtBlock; // Block when the pool was last updated uint256 tokens; // Total tokens as pool reserves uint256 shares; // Total shares minted in the pool mapping(address => Delegation) delegators; // Mapping of delegator => Delegation } /** * @dev Individual delegation data of a delegator in a pool. */ struct Delegation { uint256 shares; // Shares owned by a delegator in the pool uint256 tokensLocked; // Tokens locked for undelegation uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn } // -- Configuration -- function setMinimumIndexerStake(uint256 _minimumIndexerStake) external; function setThawingPeriod(uint32 _thawingPeriod) external; function setCurationPercentage(uint32 _percentage) external; function setProtocolPercentage(uint32 _percentage) external; function setChannelDisputeEpochs(uint32 _channelDisputeEpochs) external; function setMaxAllocationEpochs(uint32 _maxAllocationEpochs) external; function setRebateRatio(uint32 _alphaNumerator, uint32 _alphaDenominator) external; function setDelegationRatio(uint32 _delegationRatio) external; function setDelegationParameters( uint32 _indexingRewardCut, uint32 _queryFeeCut, uint32 _cooldownBlocks ) external; function setDelegationParametersCooldown(uint32 _blocks) external; function setDelegationUnbondingPeriod(uint32 _delegationUnbondingPeriod) external; function setDelegationTaxPercentage(uint32 _percentage) external; function setSlasher(address _slasher, bool _allowed) external; function setAssetHolder(address _assetHolder, bool _allowed) external; // -- Operation -- function setOperator(address _operator, bool _allowed) external; function isOperator(address _operator, address _indexer) external view returns (bool); // -- Staking -- function stake(uint256 _tokens) external; function stakeTo(address _indexer, uint256 _tokens) external; function unstake(uint256 _tokens) external; function slash( address _indexer, uint256 _tokens, uint256 _reward, address _beneficiary ) external; function withdraw() external; // -- Delegation -- function delegate(address _indexer, uint256 _tokens) external returns (uint256); function undelegate(address _indexer, uint256 _shares) external returns (uint256); function withdrawDelegated(address _indexer, address _newIndexer) external returns (uint256); // -- Channel management and allocations -- function allocate( bytes32 _subgraphDeploymentID, uint256 _tokens, address _allocationID, bytes32 _metadata, bytes calldata _proof ) external; function allocateFrom( address _indexer, bytes32 _subgraphDeploymentID, uint256 _tokens, address _allocationID, bytes32 _metadata, bytes calldata _proof ) external; function closeAllocation(address _allocationID, bytes32 _poi) external; function closeAllocationMany(CloseAllocationRequest[] calldata _requests) external; function closeAndAllocate( address _oldAllocationID, bytes32 _poi, address _indexer, bytes32 _subgraphDeploymentID, uint256 _tokens, address _allocationID, bytes32 _metadata, bytes calldata _proof ) external; function collect(uint256 _tokens, address _allocationID) external; function claim(address _allocationID, bool _restake) external; function claimMany(address[] calldata _allocationID, bool _restake) external; // -- Getters and calculations -- function hasStake(address _indexer) external view returns (bool); function getIndexerStakedTokens(address _indexer) external view returns (uint256); function getIndexerCapacity(address _indexer) external view returns (uint256); function getAllocation(address _allocationID) external view returns (Allocation memory); function getAllocationState(address _allocationID) external view returns (AllocationState); function isAllocation(address _allocationID) external view returns (bool); function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentID) external view returns (uint256); function getDelegation(address _indexer, address _delegator) external view returns (Delegation memory); function isDelegator(address _indexer, address _delegator) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IGraphToken is IERC20 { // -- Mint and Burn -- function burn(uint256 amount) external; function mint(address _to, uint256 _amount) external; // -- Mint Admin -- function addMinter(address _account) external; function removeMinter(address _account) external; function renounceMinter() external; function isMinter(address _account) external view returns (bool); // -- Permit -- function permit( address _owner, address _spender, uint256 _value, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IGraphCurationToken is IERC20 { function burnFrom(address _account, uint256 _amount) external; function mint(address _to, uint256 _amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"param","type":"string"}],"name":"ParameterUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"indexer","type":"address"},{"indexed":true,"internalType":"address","name":"allocationID","type":"address"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsAssigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"indexer","type":"address"},{"indexed":true,"internalType":"address","name":"allocationID","type":"address"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"RewardsDenied","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"subgraphDeploymentID","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"sinceBlock","type":"uint256"}],"name":"RewardsDenylistUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"controller","type":"address"}],"name":"SetController","type":"event"},{"inputs":[],"name":"accRewardsPerSignal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accRewardsPerSignalLastBlockUpdated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IGraphProxy","name":"_proxy","type":"address"}],"name":"acceptProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IGraphProxy","name":"_proxy","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"acceptProxyAndCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"addressCache","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"contract IController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"denylist","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_subgraphDeploymentID","type":"bytes32"}],"name":"getAccRewardsForSubgraph","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_subgraphDeploymentID","type":"bytes32"}],"name":"getAccRewardsPerAllocatedToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAccRewardsPerSignal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNewRewardsPerSignal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_allocationID","type":"address"}],"name":"getRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_controller","type":"address"},{"internalType":"uint256","name":"_issuanceRate","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_subgraphDeploymentID","type":"bytes32"}],"name":"isDenied","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"issuanceRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_subgraphDeploymentID","type":"bytes32"}],"name":"onSubgraphAllocationUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_subgraphDeploymentID","type":"bytes32"}],"name":"onSubgraphSignalUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_controller","type":"address"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_subgraphDeploymentID","type":"bytes32"},{"internalType":"bool","name":"_deny","type":"bool"}],"name":"setDenied","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_subgraphDeploymentID","type":"bytes32[]"},{"internalType":"bool[]","name":"_deny","type":"bool[]"}],"name":"setDeniedMany","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_issuanceRate","type":"uint256"}],"name":"setIssuanceRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_subgraphAvailabilityOracle","type":"address"}],"name":"setSubgraphAvailabilityOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subgraphAvailabilityOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"subgraphs","outputs":[{"internalType":"uint256","name":"accRewardsForSubgraph","type":"uint256"},{"internalType":"uint256","name":"accRewardsForSubgraphSnapshot","type":"uint256"},{"internalType":"uint256","name":"accRewardsPerSignalSnapshot","type":"uint256"},{"internalType":"uint256","name":"accRewardsPerAllocatedToken","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_allocationID","type":"address"}],"name":"takeRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateAccRewardsPerSignal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50611c2d806100206000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639ce7abe5116100de578063dc675a6511610097578063e820e28411610071578063e820e2841461032b578063eeac3e0e1461034b578063f77c47911461035e578063fc24ffdf146103665761018e565b8063dc675a6514610308578063e242cf1e1461031b578063e284f848146103235761018e565b80639ce7abe5146102ac578063a2594d82146102bf578063a8cc0ee2146102d2578063c7d1117d146102da578063cd6dc687146102e2578063db750926146102f55761018e565b80633c9ae2ba1161014b578063702a280e11610125578063702a280e1461025d57806379ee54f71461027e5780639006ce8b1461029157806392eefe9b146102995761018e565b80633c9ae2ba1461021f5780634986594f146102275780635c6cbd591461024a5761018e565b806305bb8c6b146101935780630903c094146101b15780631324a506146101c657806316a84ab2146101d95780631d1c2fec146101f95780631debaded1461020c575b600080fd5b61019b610379565b6040516101a891906119c1565b60405180910390f35b6101c46101bf36600461178c565b610388565b005b6101c46101d436600461186e565b6103e4565b6101ec6101e7366004611856565b610425565b6040516101a891906119f9565b6101ec610207366004611856565b610437565b6101c461021a3660046117d3565b610470565b6101ec61050f565b61023a610235366004611856565b610515565b6040516101a89493929190611b63565b6101ec610258366004611856565b61053c565b61027061026b366004611856565b610634565b6040516101a8929190611b55565b6101ec61028c36600461178c565b610740565b6101ec6107fd565b6101c46102a736600461178c565b610803565b6101c46102ba366004611899565b61086e565b6101c46102cd36600461178c565b6109c4565b6101ec610adf565b6101ec610afb565b6101c46102f03660046117a8565b610b13565b6101ec61030336600461178c565b610b7c565b61019b610316366004611856565b610d9e565b6101ec610db9565b6101ec610dbf565b61033e610339366004611856565b610f80565b6040516101a891906119ee565b6101ec610359366004611856565b610f94565b61019b610fc6565b6101c4610374366004611856565b610fd5565b600f546001600160a01b031681565b610390610fe6565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c906103d990611a02565b60405180910390a150565b600f546001600160a01b031633146104175760405162461bcd60e51b815260040161040e90611a7c565b60405180910390fd5b61042182826110a6565b5050565b60116020526000908152604090205481565b6000610441610afb565b5060008281526010602052604090206104598361053c565b808255600d5460029092019190915590505b919050565b600f546001600160a01b0316331461049a5760405162461bcd60e51b815260040161040e90611a7c565b8281146104b95760405162461bcd60e51b815260040161040e90611b34565b60005b83811015610508576105008585838181106104d357fe5b905060200201358484848181106104e657fe5b90506020020160208101906104fb919061183c565b6110a6565b6001016104bc565b5050505050565b600c5481565b60106020526000908152604090208054600182015460028301546003909301549192909184565b6000818152601060205260408120600281015482906105639061055d610adf565b90611109565b9050600061056f611154565b6001600160a01b03166346e855da866040518263ffffffff1660e01b815260040161059a91906119f9565b60206040518083038186803b1580156105b257600080fd5b505afa1580156105c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ea91906119a9565b9050806105fd576000935050505061046b565b600061061b670de0b6b3a764000061061585856111f1565b9061124a565b845490915061062a908261128c565b9695505050505050565b600081815260106020526040812081908161064e8561053c565b9050600061066983600101548361110990919063ffffffff16565b905060006106756112e6565b6001600160a01b031663e2e1e8e9886040518263ffffffff1660e01b81526004016106a091906119f9565b60206040518083038186803b1580156106b857600080fd5b505afa1580156106cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f091906119a9565b90508061070757600083955095505050505061073b565b600061071f8261061585670de0b6b3a76400006111f1565b6003860154909150610731908261128c565b9650929450505050505b915091565b600061074a6116d7565b6107526112e6565b6001600160a01b0316630e022923846040518263ffffffff1660e01b815260040161077d91906119c1565b6101006040518083038186803b15801561079657600080fd5b505afa1580156107aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ce9190611919565b905060006107df8260200151610634565b5090506107f582604001518360e0015183611352565b949350505050565b600e5481565b6000546001600160a01b03163314610862576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b61086b81611380565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156108aa57600080fd5b505af11580156108be573d6000803e3d6000fd5b505050506040513d60208110156108d457600080fd5b50516001600160a01b03163314610932576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156109a657600080fd5b505af11580156109ba573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610a0057600080fd5b505af1158015610a14573d6000803e3d6000fd5b505050506040513d6020811015610a2a57600080fd5b50516001600160a01b03163314610a88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ac357600080fd5b505af1158015610ad7573d6000803e3d6000fd5b505050505050565b6000610af5610aec610dbf565b600d549061128c565b90505b90565b6000610b05610adf565b600d81905543600e55905090565b610b1b611428565b6001600160a01b0316336001600160a01b031614610b6a5760405162461bcd60e51b8152600401808060200182810382526021815260200180611bd76021913960400191505060405180910390fd5b610b7382610862565b6104218161144d565b600080610b876112e6565b9050336001600160a01b03821614610bb15760405162461bcd60e51b815260040161040e90611af1565b6000610bbb6114b1565b9050610bc56116d7565b604051630e02292360e01b81526001600160a01b03841690630e02292390610bf19088906004016119c1565b6101006040518083038186803b158015610c0a57600080fd5b505afa158015610c1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c429190611919565b90506000610c538260200151610f94565b9050610c628260200151610f80565b15610cc757856001600160a01b031682600001516001600160a01b03167f07b6d8dafdf1323cc892f303125d1308c0edc07b15b14b6de6dcb4a5eea818fa8460800151604051610cb291906119f9565b60405180910390a3600094505050505061046b565b6000610cdc83604001518460e0015184611352565b6040516340c10f1960e01b81529091506001600160a01b038516906340c10f1990610d0d90889085906004016119d5565b600060405180830381600087803b158015610d2757600080fd5b505af1158015610d3b573d6000803e3d6000fd5b50505050866001600160a01b031683600001516001600160a01b03167f315d9cdbc182c9118c140c78a121ebb9f24bf73f841339a8a41cdc3586c34e18856080015184604051610d8c929190611b55565b60405180910390a39695505050505050565b6001602052600090815260409020546001600160a01b031681565b600d5481565b600080610dd7600e544361110990919063ffffffff16565b905080610de8576000915050610af8565b670de0b6b3a7640000600c5411610e03576000915050610af8565b6000610e0d6114b1565b90506000816001600160a01b03166370a08231610e28611154565b6040518263ffffffff1660e01b8152600401610e4491906119c1565b60206040518083038186803b158015610e5c57600080fd5b505afa158015610e70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9491906119a9565b905080610ea75760009350505050610af8565b6000600c5490506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ee957600080fd5b505afa158015610efd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2191906119a9565b90506000610f4e670de0b6b3a7640000610615610f47868a670de0b6b3a764000061151d565b85906111f1565b90506000610f5c8284611109565b9050610f748561061583670de0b6b3a76400006111f1565b97505050505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180610fad85610634565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b610fdd610fe6565b61086b8161144d565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561103257600080fd5b505afa158015611046573d6000803e3d6000fd5b505050506040513d602081101561105c57600080fd5b50516001600160a01b031633146110a45760405162461bcd60e51b8152600401808060200182810382526022815260200180611bb56022913960400191505060405180910390fd5b565b6000816110b45760006110b6565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a906110fc9084906119f9565b60405180910390a2505050565b600061114b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506115db565b90505b92915050565b6000805460408051637bb20d2f60e11b81527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f600482015290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156111c057600080fd5b505afa1580156111d4573d6000803e3d6000fd5b505050506040513d60208110156111ea57600080fd5b5051905090565b6000826112005750600061114e565b8282028284828161120d57fe5b041461114b5760405162461bcd60e51b8152600401808060200182810382526021815260200180611b946021913960400191505060405180910390fd5b600061114b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611672565b60008282018381101561114b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000805460408051637bb20d2f60e11b81527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034600482015290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156111c057600080fd5b60008061135f8385611109565b9050611377670de0b6b3a764000061061583886111f1565b95945050505050565b6001600160a01b0381166113d4576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b670de0b6b3a76400008110156114755760405162461bcd60e51b815260040161040e90611a39565b61147d610afb565b50600c8190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c906103d990611acb565b6000805460408051637bb20d2f60e11b81527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247600482015290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156111c057600080fd5b60008380156115bd576001841680156115385785925061153c565b8392505b50600283046002850494505b84156115b757858602868782041461155f57600080fd5b8181018181101561156f57600080fd5b85900496505060018516156115ac57858302838782041415871515161561159557600080fd5b818101818110156115a557600080fd5b8590049350505b600285049450611548565b506115d3565b8380156115cd57600092506115d1565b8392505b505b509392505050565b6000818484111561166a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561162f578181015183820152602001611617565b50505050905090810190601f16801561165c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836116c15760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561162f578181015183820152602001611617565b5060008385816116cd57fe5b0495945050505050565b60405180610100016040528060006001600160a01b03168152602001600080191681526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b805161046b81611b7e565b60008083601f840112611744578182fd5b50813567ffffffffffffffff81111561175b578182fd5b602083019150836020808302850101111561177557600080fd5b9250929050565b8035801515811461046b57600080fd5b60006020828403121561179d578081fd5b813561114b81611b7e565b600080604083850312156117ba578081fd5b82356117c581611b7e565b946020939093013593505050565b600080600080604085870312156117e8578182fd5b843567ffffffffffffffff808211156117ff578384fd5b61180b88838901611733565b90965094506020870135915080821115611823578384fd5b5061183087828801611733565b95989497509550505050565b60006020828403121561184d578081fd5b61114b8261177c565b600060208284031215611867578081fd5b5035919050565b60008060408385031215611880578182fd5b823591506118906020840161177c565b90509250929050565b6000806000604084860312156118ad578283fd5b83356118b881611b7e565b9250602084013567ffffffffffffffff808211156118d4578384fd5b818601915086601f8301126118e7578384fd5b8135818111156118f5578485fd5b876020828501011115611906578485fd5b6020830194508093505050509250925092565b600061010080838503121561192c578182fd5b6040519081019067ffffffffffffffff8211818310171561194957fe5b8160405261195684611728565b81526020840151602082015260408401516040820152606084015160608201526080840151608082015260a084015160a082015260c084015160c082015260e084015160e0820152809250505092915050565b6000602082840312156119ba578081fd5b5051919050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b60208082526023908201527f49737375616e6365207261746520756e646572206d696e696d756d20616c6c6f6040820152621dd95960ea1b606082015260800190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252600c908201526b69737375616e63655261746560a01b604082015260600190565b60208082526023908201527f43616c6c6572206d75737420626520746865207374616b696e6720636f6e74726040820152621858dd60ea1b606082015260800190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461086b57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206d75737420626520436f6e74726f6c6c657220676f7665726e6f7243616c6c6572206d7573742062652074686520696d706c656d656e746174696f6ea2646970667358221220a002cd24dc390f17b6944d68d32e345ae62f4f424f5cff28d60a4cf57180d93864736f6c63430007040033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061018e5760003560e01c80639ce7abe5116100de578063dc675a6511610097578063e820e28411610071578063e820e2841461032b578063eeac3e0e1461034b578063f77c47911461035e578063fc24ffdf146103665761018e565b8063dc675a6514610308578063e242cf1e1461031b578063e284f848146103235761018e565b80639ce7abe5146102ac578063a2594d82146102bf578063a8cc0ee2146102d2578063c7d1117d146102da578063cd6dc687146102e2578063db750926146102f55761018e565b80633c9ae2ba1161014b578063702a280e11610125578063702a280e1461025d57806379ee54f71461027e5780639006ce8b1461029157806392eefe9b146102995761018e565b80633c9ae2ba1461021f5780634986594f146102275780635c6cbd591461024a5761018e565b806305bb8c6b146101935780630903c094146101b15780631324a506146101c657806316a84ab2146101d95780631d1c2fec146101f95780631debaded1461020c575b600080fd5b61019b610379565b6040516101a891906119c1565b60405180910390f35b6101c46101bf36600461178c565b610388565b005b6101c46101d436600461186e565b6103e4565b6101ec6101e7366004611856565b610425565b6040516101a891906119f9565b6101ec610207366004611856565b610437565b6101c461021a3660046117d3565b610470565b6101ec61050f565b61023a610235366004611856565b610515565b6040516101a89493929190611b63565b6101ec610258366004611856565b61053c565b61027061026b366004611856565b610634565b6040516101a8929190611b55565b6101ec61028c36600461178c565b610740565b6101ec6107fd565b6101c46102a736600461178c565b610803565b6101c46102ba366004611899565b61086e565b6101c46102cd36600461178c565b6109c4565b6101ec610adf565b6101ec610afb565b6101c46102f03660046117a8565b610b13565b6101ec61030336600461178c565b610b7c565b61019b610316366004611856565b610d9e565b6101ec610db9565b6101ec610dbf565b61033e610339366004611856565b610f80565b6040516101a891906119ee565b6101ec610359366004611856565b610f94565b61019b610fc6565b6101c4610374366004611856565b610fd5565b600f546001600160a01b031681565b610390610fe6565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c906103d990611a02565b60405180910390a150565b600f546001600160a01b031633146104175760405162461bcd60e51b815260040161040e90611a7c565b60405180910390fd5b61042182826110a6565b5050565b60116020526000908152604090205481565b6000610441610afb565b5060008281526010602052604090206104598361053c565b808255600d5460029092019190915590505b919050565b600f546001600160a01b0316331461049a5760405162461bcd60e51b815260040161040e90611a7c565b8281146104b95760405162461bcd60e51b815260040161040e90611b34565b60005b83811015610508576105008585838181106104d357fe5b905060200201358484848181106104e657fe5b90506020020160208101906104fb919061183c565b6110a6565b6001016104bc565b5050505050565b600c5481565b60106020526000908152604090208054600182015460028301546003909301549192909184565b6000818152601060205260408120600281015482906105639061055d610adf565b90611109565b9050600061056f611154565b6001600160a01b03166346e855da866040518263ffffffff1660e01b815260040161059a91906119f9565b60206040518083038186803b1580156105b257600080fd5b505afa1580156105c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ea91906119a9565b9050806105fd576000935050505061046b565b600061061b670de0b6b3a764000061061585856111f1565b9061124a565b845490915061062a908261128c565b9695505050505050565b600081815260106020526040812081908161064e8561053c565b9050600061066983600101548361110990919063ffffffff16565b905060006106756112e6565b6001600160a01b031663e2e1e8e9886040518263ffffffff1660e01b81526004016106a091906119f9565b60206040518083038186803b1580156106b857600080fd5b505afa1580156106cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f091906119a9565b90508061070757600083955095505050505061073b565b600061071f8261061585670de0b6b3a76400006111f1565b6003860154909150610731908261128c565b9650929450505050505b915091565b600061074a6116d7565b6107526112e6565b6001600160a01b0316630e022923846040518263ffffffff1660e01b815260040161077d91906119c1565b6101006040518083038186803b15801561079657600080fd5b505afa1580156107aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ce9190611919565b905060006107df8260200151610634565b5090506107f582604001518360e0015183611352565b949350505050565b600e5481565b6000546001600160a01b03163314610862576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b61086b81611380565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156108aa57600080fd5b505af11580156108be573d6000803e3d6000fd5b505050506040513d60208110156108d457600080fd5b50516001600160a01b03163314610932576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156109a657600080fd5b505af11580156109ba573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610a0057600080fd5b505af1158015610a14573d6000803e3d6000fd5b505050506040513d6020811015610a2a57600080fd5b50516001600160a01b03163314610a88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ac357600080fd5b505af1158015610ad7573d6000803e3d6000fd5b505050505050565b6000610af5610aec610dbf565b600d549061128c565b90505b90565b6000610b05610adf565b600d81905543600e55905090565b610b1b611428565b6001600160a01b0316336001600160a01b031614610b6a5760405162461bcd60e51b8152600401808060200182810382526021815260200180611bd76021913960400191505060405180910390fd5b610b7382610862565b6104218161144d565b600080610b876112e6565b9050336001600160a01b03821614610bb15760405162461bcd60e51b815260040161040e90611af1565b6000610bbb6114b1565b9050610bc56116d7565b604051630e02292360e01b81526001600160a01b03841690630e02292390610bf19088906004016119c1565b6101006040518083038186803b158015610c0a57600080fd5b505afa158015610c1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c429190611919565b90506000610c538260200151610f94565b9050610c628260200151610f80565b15610cc757856001600160a01b031682600001516001600160a01b03167f07b6d8dafdf1323cc892f303125d1308c0edc07b15b14b6de6dcb4a5eea818fa8460800151604051610cb291906119f9565b60405180910390a3600094505050505061046b565b6000610cdc83604001518460e0015184611352565b6040516340c10f1960e01b81529091506001600160a01b038516906340c10f1990610d0d90889085906004016119d5565b600060405180830381600087803b158015610d2757600080fd5b505af1158015610d3b573d6000803e3d6000fd5b50505050866001600160a01b031683600001516001600160a01b03167f315d9cdbc182c9118c140c78a121ebb9f24bf73f841339a8a41cdc3586c34e18856080015184604051610d8c929190611b55565b60405180910390a39695505050505050565b6001602052600090815260409020546001600160a01b031681565b600d5481565b600080610dd7600e544361110990919063ffffffff16565b905080610de8576000915050610af8565b670de0b6b3a7640000600c5411610e03576000915050610af8565b6000610e0d6114b1565b90506000816001600160a01b03166370a08231610e28611154565b6040518263ffffffff1660e01b8152600401610e4491906119c1565b60206040518083038186803b158015610e5c57600080fd5b505afa158015610e70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9491906119a9565b905080610ea75760009350505050610af8565b6000600c5490506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ee957600080fd5b505afa158015610efd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2191906119a9565b90506000610f4e670de0b6b3a7640000610615610f47868a670de0b6b3a764000061151d565b85906111f1565b90506000610f5c8284611109565b9050610f748561061583670de0b6b3a76400006111f1565b97505050505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180610fad85610634565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b610fdd610fe6565b61086b8161144d565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561103257600080fd5b505afa158015611046573d6000803e3d6000fd5b505050506040513d602081101561105c57600080fd5b50516001600160a01b031633146110a45760405162461bcd60e51b8152600401808060200182810382526022815260200180611bb56022913960400191505060405180910390fd5b565b6000816110b45760006110b6565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a906110fc9084906119f9565b60405180910390a2505050565b600061114b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506115db565b90505b92915050565b6000805460408051637bb20d2f60e11b81527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f600482015290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156111c057600080fd5b505afa1580156111d4573d6000803e3d6000fd5b505050506040513d60208110156111ea57600080fd5b5051905090565b6000826112005750600061114e565b8282028284828161120d57fe5b041461114b5760405162461bcd60e51b8152600401808060200182810382526021815260200180611b946021913960400191505060405180910390fd5b600061114b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611672565b60008282018381101561114b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000805460408051637bb20d2f60e11b81527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034600482015290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156111c057600080fd5b60008061135f8385611109565b9050611377670de0b6b3a764000061061583886111f1565b95945050505050565b6001600160a01b0381166113d4576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b670de0b6b3a76400008110156114755760405162461bcd60e51b815260040161040e90611a39565b61147d610afb565b50600c8190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c906103d990611acb565b6000805460408051637bb20d2f60e11b81527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247600482015290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156111c057600080fd5b60008380156115bd576001841680156115385785925061153c565b8392505b50600283046002850494505b84156115b757858602868782041461155f57600080fd5b8181018181101561156f57600080fd5b85900496505060018516156115ac57858302838782041415871515161561159557600080fd5b818101818110156115a557600080fd5b8590049350505b600285049450611548565b506115d3565b8380156115cd57600092506115d1565b8392505b505b509392505050565b6000818484111561166a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561162f578181015183820152602001611617565b50505050905090810190601f16801561165c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836116c15760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561162f578181015183820152602001611617565b5060008385816116cd57fe5b0495945050505050565b60405180610100016040528060006001600160a01b03168152602001600080191681526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b805161046b81611b7e565b60008083601f840112611744578182fd5b50813567ffffffffffffffff81111561175b578182fd5b602083019150836020808302850101111561177557600080fd5b9250929050565b8035801515811461046b57600080fd5b60006020828403121561179d578081fd5b813561114b81611b7e565b600080604083850312156117ba578081fd5b82356117c581611b7e565b946020939093013593505050565b600080600080604085870312156117e8578182fd5b843567ffffffffffffffff808211156117ff578384fd5b61180b88838901611733565b90965094506020870135915080821115611823578384fd5b5061183087828801611733565b95989497509550505050565b60006020828403121561184d578081fd5b61114b8261177c565b600060208284031215611867578081fd5b5035919050565b60008060408385031215611880578182fd5b823591506118906020840161177c565b90509250929050565b6000806000604084860312156118ad578283fd5b83356118b881611b7e565b9250602084013567ffffffffffffffff808211156118d4578384fd5b818601915086601f8301126118e7578384fd5b8135818111156118f5578485fd5b876020828501011115611906578485fd5b6020830194508093505050509250925092565b600061010080838503121561192c578182fd5b6040519081019067ffffffffffffffff8211818310171561194957fe5b8160405261195684611728565b81526020840151602082015260408401516040820152606084015160608201526080840151608082015260a084015160a082015260c084015160c082015260e084015160e0820152809250505092915050565b6000602082840312156119ba578081fd5b5051919050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b60208082526023908201527f49737375616e6365207261746520756e646572206d696e696d756d20616c6c6f6040820152621dd95960ea1b606082015260800190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252600c908201526b69737375616e63655261746560a01b604082015260600190565b60208082526023908201527f43616c6c6572206d75737420626520746865207374616b696e6720636f6e74726040820152621858dd60ea1b606082015260800190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461086b57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206d75737420626520436f6e74726f6c6c657220676f7665726e6f7243616c6c6572206d7573742062652074686520696d706c656d656e746174696f6ea2646970667358221220a002cd24dc390f17b6944d68d32e345ae62f4f424f5cff28d60a4cf57180d93864736f6c63430007040033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.