diff --git a/packages/contracts/contracts/arbitrum/AddressAliasHelper.sol b/packages/contracts/contracts/arbitrum/AddressAliasHelper.sol index 740b70361..005df41c0 100644 --- a/packages/contracts/contracts/arbitrum/AddressAliasHelper.sol +++ b/packages/contracts/contracts/arbitrum/AddressAliasHelper.sol @@ -25,8 +25,15 @@ pragma solidity ^0.7.6; +/** + * @title Address Alias Helper Library + * @author Edge & Node + * @notice Utility library for converting addresses between L1 and L2 in Arbitrum + */ library AddressAliasHelper { - uint160 constant offset = uint160(0x1111000000000000000000000000000000001111); + /// @dev Offset used for L1 to L2 address aliasing + // solhint-disable-next-line const-name-snakecase + uint160 internal constant offset = uint160(0x1111000000000000000000000000000000001111); /// @notice Utility function that converts the address in the L1 that submitted a tx to /// the inbox to the msg.sender viewed in the L2 diff --git a/packages/contracts/contracts/arbitrum/IArbToken.sol b/packages/contracts/contracts/arbitrum/IArbToken.sol deleted file mode 100644 index d7d5a2d8c..000000000 --- a/packages/contracts/contracts/arbitrum/IArbToken.sol +++ /dev/null @@ -1,47 +0,0 @@ -// 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 (pablo@edgeandnode.com) - * - */ - -/** - * @title Minimum expected interface for L2 token that interacts with the L2 token bridge (this is the interface necessary - * for a custom token that interacts with the bridge, see TestArbCustomToken.sol for an example implementation). - */ -pragma solidity ^0.7.6; - -interface IArbToken { - /** - * @notice should increase token supply by amount, and should (probably) only be callable by the L1 bridge. - */ - function bridgeMint(address account, uint256 amount) external; - - /** - * @notice should decrease token supply by amount, and should (probably) only be callable by the L1 bridge. - */ - function bridgeBurn(address account, uint256 amount) external; - - /** - * @return address of layer 1 token - */ - function l1Address() external view returns (address); -} diff --git a/packages/contracts/contracts/arbitrum/IBridge.sol b/packages/contracts/contracts/arbitrum/IBridge.sol deleted file mode 100644 index 536ee075b..000000000 --- a/packages/contracts/contracts/arbitrum/IBridge.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/* - * Copyright 2021, 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-eth - * - * MODIFIED from Offchain Labs' implementation: - * - Changed solidity version to 0.7.6 (pablo@edgeandnode.com) - * - */ - -pragma solidity ^0.7.6; - -interface IBridge { - event MessageDelivered( - uint256 indexed messageIndex, - bytes32 indexed beforeInboxAcc, - address inbox, - uint8 kind, - address sender, - bytes32 messageDataHash - ); - - event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data); - - event InboxToggle(address indexed inbox, bool enabled); - - event OutboxToggle(address indexed outbox, bool enabled); - - function deliverMessageToInbox( - uint8 kind, - address sender, - bytes32 messageDataHash - ) external payable returns (uint256); - - function executeCall( - address destAddr, - uint256 amount, - bytes calldata data - ) external returns (bool success, bytes memory returnData); - - // These are only callable by the admin - function setInbox(address inbox, bool enabled) external; - - function setOutbox(address inbox, bool enabled) external; - - // View functions - - function activeOutbox() external view returns (address); - - function allowedInboxes(address inbox) external view returns (bool); - - function allowedOutboxes(address outbox) external view returns (bool); - - function inboxAccs(uint256 index) external view returns (bytes32); - - function messageCount() external view returns (uint256); -} diff --git a/packages/contracts/contracts/arbitrum/IInbox.sol b/packages/contracts/contracts/arbitrum/IInbox.sol deleted file mode 100644 index a9315bbf8..000000000 --- a/packages/contracts/contracts/arbitrum/IInbox.sol +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/* - * Copyright 2021, 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-eth - * - * MODIFIED from Offchain Labs' implementation: - * - Changed solidity version to 0.7.6 (pablo@edgeandnode.com) - * - */ - -pragma solidity ^0.7.6; - -import "./IBridge.sol"; -import "./IMessageProvider.sol"; - -interface IInbox is IMessageProvider { - function sendL2Message(bytes calldata messageData) external returns (uint256); - - function sendUnsignedTransaction( - uint256 maxGas, - uint256 gasPriceBid, - uint256 nonce, - address destAddr, - uint256 amount, - bytes calldata data - ) external returns (uint256); - - function sendContractTransaction( - uint256 maxGas, - uint256 gasPriceBid, - address destAddr, - uint256 amount, - bytes calldata data - ) external returns (uint256); - - function sendL1FundedUnsignedTransaction( - uint256 maxGas, - uint256 gasPriceBid, - uint256 nonce, - address destAddr, - bytes calldata data - ) external payable returns (uint256); - - function sendL1FundedContractTransaction( - uint256 maxGas, - uint256 gasPriceBid, - address destAddr, - bytes calldata data - ) external payable returns (uint256); - - function createRetryableTicket( - address destAddr, - uint256 arbTxCallValue, - uint256 maxSubmissionCost, - address submissionRefundAddress, - address valueRefundAddress, - uint256 maxGas, - uint256 gasPriceBid, - bytes calldata data - ) external payable returns (uint256); - - function depositEth(uint256 maxSubmissionCost) external payable returns (uint256); - - function bridge() external view returns (IBridge); - - function pauseCreateRetryables() external; - - function unpauseCreateRetryables() external; - - function startRewriteAddress() external; - - function stopRewriteAddress() external; -} diff --git a/packages/contracts/contracts/arbitrum/IMessageProvider.sol b/packages/contracts/contracts/arbitrum/IMessageProvider.sol deleted file mode 100644 index 8fbfdb171..000000000 --- a/packages/contracts/contracts/arbitrum/IMessageProvider.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/* - * Copyright 2021, 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-eth - * - * MODIFIED from Offchain Labs' implementation: - * - Changed solidity version to 0.7.6 (pablo@edgeandnode.com) - * - */ - -pragma solidity ^0.7.6; - -interface IMessageProvider { - event InboxMessageDelivered(uint256 indexed messageNum, bytes data); - - event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); -} diff --git a/packages/contracts/contracts/arbitrum/IOutbox.sol b/packages/contracts/contracts/arbitrum/IOutbox.sol deleted file mode 100644 index 2e4f05bd5..000000000 --- a/packages/contracts/contracts/arbitrum/IOutbox.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/* - * Copyright 2021, 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-eth - * - * MODIFIED from Offchain Labs' implementation: - * - Changed solidity version to 0.7.6 (pablo@edgeandnode.com) - * - */ - -pragma solidity ^0.7.6; - -interface IOutbox { - event OutboxEntryCreated( - uint256 indexed batchNum, - uint256 outboxEntryIndex, - bytes32 outputRoot, - uint256 numInBatch - ); - event OutBoxTransactionExecuted( - address indexed destAddr, - address indexed l2Sender, - uint256 indexed outboxEntryIndex, - uint256 transactionIndex - ); - - function l2ToL1Sender() external view returns (address); - - function l2ToL1Block() external view returns (uint256); - - function l2ToL1EthBlock() external view returns (uint256); - - function l2ToL1Timestamp() external view returns (uint256); - - function l2ToL1BatchNum() external view returns (uint256); - - function l2ToL1OutputId() external view returns (bytes32); - - function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths) external; - - function outboxEntryExists(uint256 batchNum) external view returns (bool); -} diff --git a/packages/contracts/contracts/arbitrum/ITokenGateway.sol b/packages/contracts/contracts/arbitrum/ITokenGateway.sol deleted file mode 100644 index 3b12e578e..000000000 --- a/packages/contracts/contracts/arbitrum/ITokenGateway.sol +++ /dev/null @@ -1,74 +0,0 @@ -// 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 (pablo@edgeandnode.com) - * - */ - -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); -} diff --git a/packages/contracts/contracts/arbitrum/L1ArbitrumMessenger.sol b/packages/contracts/contracts/arbitrum/L1ArbitrumMessenger.sol index 839e1930b..0428e9b87 100644 --- a/packages/contracts/contracts/arbitrum/L1ArbitrumMessenger.sol +++ b/packages/contracts/contracts/arbitrum/L1ArbitrumMessenger.sol @@ -25,20 +25,49 @@ pragma solidity ^0.7.6; -import "./IInbox.sol"; -import "./IOutbox.sol"; +import { IInbox } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/IInbox.sol"; +import { IOutbox } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/IOutbox.sol"; +import { IBridge } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/IBridge.sol"; -/// @notice L1 utility contract to assist with L1 <=> L2 interactions -/// @dev this is an abstract contract instead of library so the functions can be easily overridden when testing +/** + * @title L1 Arbitrum Messenger + * @author Edge & Node + * @notice L1 utility contract to assist with L1 <=> L2 interactions + * @dev this is an abstract contract instead of library so the functions can be easily overridden when testing + */ abstract contract L1ArbitrumMessenger { + /** + * @notice Emitted when a transaction is sent to L2 + * @param _from Address sending the transaction + * @param _to Address receiving the transaction on L2 + * @param _seqNum Sequence number of the retryable ticket + * @param _data Transaction data + */ event TxToL2(address indexed _from, address indexed _to, uint256 indexed _seqNum, bytes _data); + /** + * @dev Parameters for L2 gas configuration + * @param _maxSubmissionCost Maximum cost for submitting the transaction + * @param _maxGas Maximum gas for the L2 transaction + * @param _gasPriceBid Gas price bid for the L2 transaction + */ struct L2GasParams { uint256 _maxSubmissionCost; uint256 _maxGas; uint256 _gasPriceBid; } + /** + * @notice Send a transaction to L2 using gas parameters struct + * @param _inbox Address of the inbox contract + * @param _to Destination address on L2 + * @param _user Address that will be credited as the sender + * @param _l1CallValue ETH value to send with the L1 transaction + * @param _l2CallValue ETH value to send with the L2 transaction + * @param _l2GasParams Gas parameters for the L2 transaction + * @param _data Calldata for the L2 transaction + * @return Sequence number of the retryable ticket + */ function sendTxToL2( address _inbox, address _to, @@ -63,6 +92,19 @@ abstract contract L1ArbitrumMessenger { ); } + /** + * @notice Send a transaction to L2 with individual gas parameters + * @param _inbox Address of the inbox contract + * @param _to Destination address on L2 + * @param _user Address that will be credited as the sender + * @param _l1CallValue ETH value to send with the L1 transaction + * @param _l2CallValue ETH value to send with the L2 transaction + * @param _maxSubmissionCost Maximum cost for submitting the transaction + * @param _maxGas Maximum gas for the L2 transaction + * @param _gasPriceBid Gas price bid for the L2 transaction + * @param _data Calldata for the L2 transaction + * @return Sequence number of the retryable ticket + */ function sendTxToL2( address _inbox, address _to, @@ -88,11 +130,21 @@ abstract contract L1ArbitrumMessenger { return seqNum; } + /** + * @notice Get the bridge contract from an inbox + * @param _inbox Address of the inbox contract + * @return Bridge contract interface + */ function getBridge(address _inbox) internal view virtual returns (IBridge) { return IInbox(_inbox).bridge(); } - /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies + /** + * @notice Get the L2 to L1 sender address from the outbox + * @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies + * @param _inbox Address of the inbox contract + * @return Address of the L2 to L1 sender + */ function getL2ToL1Sender(address _inbox) internal view virtual returns (address) { IOutbox outbox = IOutbox(getBridge(_inbox).activeOutbox()); address l2ToL1Sender = outbox.l2ToL1Sender(); diff --git a/packages/contracts/contracts/arbitrum/L2ArbitrumMessenger.sol b/packages/contracts/contracts/arbitrum/L2ArbitrumMessenger.sol index e34a29262..ac6774748 100644 --- a/packages/contracts/contracts/arbitrum/L2ArbitrumMessenger.sol +++ b/packages/contracts/contracts/arbitrum/L2ArbitrumMessenger.sol @@ -25,15 +25,35 @@ pragma solidity ^0.7.6; -import "arbos-precompiles/arbos/builtin/ArbSys.sol"; +import { ArbSys } from "arbos-precompiles/arbos/builtin/ArbSys.sol"; -/// @notice L2 utility contract to assist with L1 <=> L2 interactions -/// @dev this is an abstract contract instead of library so the functions can be easily overridden when testing +/** + * @title L2 Arbitrum Messenger + * @author Edge & Node + * @notice L2 utility contract to assist with L1 <=> L2 interactions + * @dev this is an abstract contract instead of library so the functions can be easily overridden when testing + */ abstract contract L2ArbitrumMessenger { + /// @dev Address of the ArbSys precompile address internal constant ARB_SYS_ADDRESS = address(100); + /** + * @notice Emitted when a transaction is sent to L1 + * @param _from Address sending the transaction + * @param _to Address receiving the transaction on L1 + * @param _id ID of the L2 to L1 message + * @param _data Transaction data + */ event TxToL1(address indexed _from, address indexed _to, uint256 indexed _id, bytes _data); + /** + * @notice Send a transaction from L2 to L1 + * @param _l1CallValue ETH value to send with the L1 transaction + * @param _from Address that is sending the transaction + * @param _to Destination address on L1 + * @param _data Calldata for the L1 transaction + * @return ID of the L2 to L1 message + */ function sendTxToL1( uint256 _l1CallValue, address _from, diff --git a/packages/contracts/contracts/bancor/BancorFormula.sol b/packages/contracts/contracts/bancor/BancorFormula.sol index 689eebaba..0d221be56 100644 --- a/packages/contracts/contracts/bancor/BancorFormula.sol +++ b/packages/contracts/contracts/bancor/BancorFormula.sol @@ -2,35 +2,55 @@ pragma solidity ^0.7.6; -import "@openzeppelin/contracts/math/SafeMath.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable function-max-lines, gas-increment-by-one, gas-strict-inequalities +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; + +/** + * @title Bancor Formula Contract + * @author Edge & Node + * @notice Contract implementing Bancor's bonding curve formula for token conversion + */ contract BancorFormula { using SafeMath for uint256; - uint16 public constant version = 6; + /// @notice Version of the Bancor formula implementation + uint16 public constant version = 6; // solhint-disable-line const-name-snakecase + /// @dev Constant representing the value 1 uint256 private constant ONE = 1; + /// @dev Maximum ratio value (100% in parts per million) uint32 private constant MAX_RATIO = 1000000; + /// @dev Minimum precision for calculations uint8 private constant MIN_PRECISION = 32; + /// @dev Maximum precision for calculations uint8 private constant MAX_PRECISION = 127; /** * @dev Auto-generated via 'PrintIntScalingFactors.py' */ + /// @dev Fixed point representation of 1 (2^127) uint256 private constant FIXED_1 = 0x080000000000000000000000000000000; + /// @dev Fixed point representation of 2 (2^128) uint256 private constant FIXED_2 = 0x100000000000000000000000000000000; + /// @dev Maximum number for calculations (2^129) uint256 private constant MAX_NUM = 0x200000000000000000000000000000000; /** * @dev Auto-generated via 'PrintLn2ScalingFactors.py' */ + /// @dev Natural logarithm of 2 numerator for fixed point calculations uint256 private constant LN2_NUMERATOR = 0x3f80fe03f80fe03f80fe03f80fe03f8; + /// @dev Natural logarithm of 2 denominator for fixed point calculations uint256 private constant LN2_DENOMINATOR = 0x5b9de1d10bf4103d647b0955897ba80; /** * @dev Auto-generated via 'PrintFunctionOptimalLog.py' and 'PrintFunctionOptimalExp.py' */ + /// @dev Maximum value for optimal logarithm calculation uint256 private constant OPT_LOG_MAX_VAL = 0x15bf0a8b1457695355fb8ac404e7a79e3; + /// @dev Maximum value for optimal exponentiation calculation uint256 private constant OPT_EXP_MAX_VAL = 0x800000000000000000000000000000000; /** @@ -38,6 +58,7 @@ contract BancorFormula { */ uint256[128] private maxExpArray; + /// @notice Initialize the Bancor formula with maximum exponent array values constructor() { // maxExpArray[ 0] = 0x6bffffffffffffffffffffffffffffffff; // maxExpArray[ 1] = 0x67ffffffffffffffffffffffffffffffff; @@ -170,7 +191,7 @@ contract BancorFormula { } /** - * @dev given a token supply, reserve balance, ratio and a deposit amount (in the reserve token), + * @notice Given a token supply, reserve balance, ratio and a deposit amount (in the reserve token), * calculates the return for a given conversion (in the main token) * * Formula: @@ -210,7 +231,7 @@ contract BancorFormula { } /** - * @dev given a token supply, reserve balance, ratio and a sell amount (in the main token), + * @notice Given a token supply, reserve balance, ratio and a sell amount (in the main token), * calculates the return for a given conversion (in the reserve token) * * Formula: @@ -258,7 +279,7 @@ contract BancorFormula { } /** - * @dev given two reserve balances/ratios and a sell amount (in the first reserve token), + * @notice Given two reserve balances/ratios and a sell amount (in the first reserve token), * calculates the return for a conversion from the first reserve token to the second reserve token (in the second reserve token) * note that prior to version 4, you should use 'calculateCrossConnectorReturn' instead * @@ -304,7 +325,7 @@ contract BancorFormula { } /** - * @dev given a smart token supply, reserve balance, total ratio and an amount of requested smart tokens, + * @notice Given a smart token supply, reserve balance, total ratio and an amount of requested smart tokens, * calculates the amount of reserve tokens required for purchasing the given amount of smart tokens * * Formula: @@ -341,7 +362,7 @@ contract BancorFormula { } /** - * @dev given a smart token supply, reserve balance, total ratio and an amount of smart tokens to liquidate, + * @notice Given a smart token supply, reserve balance, total ratio and an amount of smart tokens to liquidate, * calculates the amount of reserve tokens received for selling the given amount of smart tokens * * Formula: @@ -384,7 +405,7 @@ contract BancorFormula { } /** - * @dev General Description: + * @notice General Description: * Determine a value of precision. * Calculate an integer approximation of (_baseN / _baseD) ^ (_expN / _expD) * 2 ^ precision. * Return the result along with the precision used. @@ -400,6 +421,12 @@ contract BancorFormula { * This allows us to compute "base ^ exp" with maximum accuracy and without exceeding 256 bits in any of the intermediate computations. * This functions assumes that "_expN < 2 ^ 256 / log(MAX_NUM - 1)", otherwise the multiplication should be replaced with a "safeMul". * Since we rely on unsigned-integer arithmetic and "base < 1" ==> "log(base) < 0", this function does not support "_baseN < _baseD". + * @param _baseN Base numerator + * @param _baseD Base denominator + * @param _expN Exponent numerator + * @param _expD Exponent denominator + * @return result The computed power result + * @return precision The precision used in the calculation */ function power(uint256 _baseN, uint256 _baseD, uint32 _expN, uint32 _expD) internal view returns (uint256, uint8) { require(_baseN < MAX_NUM); @@ -422,8 +449,10 @@ contract BancorFormula { } /** - * @dev computes log(x / FIXED_1) * FIXED_1. + * @notice Computes log(x / FIXED_1) * FIXED_1. * This functions assumes that "x >= FIXED_1", because the output would be negative otherwise. + * @param x The input value (must be >= FIXED_1) + * @return The computed logarithm */ function generalLog(uint256 x) internal pure returns (uint256) { uint256 res = 0; @@ -450,7 +479,9 @@ contract BancorFormula { } /** - * @dev computes the largest integer smaller than or equal to the binary logarithm of the input. + * @notice Computes the largest integer smaller than or equal to the binary logarithm of the input. + * @param _n The input value + * @return The floor of the binary logarithm */ function floorLog2(uint256 _n) internal pure returns (uint8) { uint8 res = 0; @@ -475,9 +506,11 @@ contract BancorFormula { } /** - * @dev the global "maxExpArray" is sorted in descending order, and therefore the following statements are equivalent: + * @notice The global "maxExpArray" is sorted in descending order, and therefore the following statements are equivalent: * - This function finds the position of [the smallest value in "maxExpArray" larger than or equal to "x"] * - This function finds the highest position of [a value in "maxExpArray" larger than or equal to "x"] + * @param _x The value to find position for + * @return The position in the maxExpArray */ function findPositionInMaxExpArray(uint256 _x) internal view returns (uint8) { uint8 lo = MIN_PRECISION; @@ -497,11 +530,14 @@ contract BancorFormula { } /** - * @dev this function can be auto-generated by the script 'PrintFunctionGeneralExp.py'. + * @notice This function can be auto-generated by the script 'PrintFunctionGeneralExp.py'. * it approximates "e ^ x" via maclaurin summation: "(x^0)/0! + (x^1)/1! + ... + (x^n)/n!". * it returns "e ^ (x / 2 ^ precision) * 2 ^ precision", that is, the result is upshifted for accuracy. * the global "maxExpArray" maps each "precision" to "((maximumExponent + 1) << (MAX_PRECISION - precision)) - 1". * the maximum permitted value for "x" is therefore given by "maxExpArray[precision] >> (MAX_PRECISION - precision)". + * @param _x The exponent value + * @param _precision The precision to use + * @return The computed exponential result */ function generalExp(uint256 _x, uint8 _precision) internal pure returns (uint256) { uint256 xi = _x; @@ -576,7 +612,7 @@ contract BancorFormula { } /** - * @dev computes log(x / FIXED_1) * FIXED_1 + * @notice Computes log(x / FIXED_1) * FIXED_1 * Input range: FIXED_1 <= x <= LOG_EXP_MAX_VAL - 1 * Auto-generated via 'PrintFunctionOptimalLog.py' * Detailed description: @@ -585,6 +621,8 @@ contract BancorFormula { * - The natural logarithm of r is calculated via Taylor series for log(1 + x), where x = r - 1 * - The natural logarithm of the input is calculated by summing up the intermediate results above * - For example: log(250) = log(e^4 * e^1 * e^0.5 * 1.021692859) = 4 + 1 + 0.5 + log(1 + 0.021692859) + * @param x The input value + * @return The computed logarithm */ function optimalLog(uint256 x) internal pure returns (uint256) { uint256 res = 0; @@ -648,7 +686,7 @@ contract BancorFormula { } /** - * @dev computes e ^ (x / FIXED_1) * FIXED_1 + * @notice Computes e ^ (x / FIXED_1) * FIXED_1 * input range: 0 <= x <= OPT_EXP_MAX_VAL - 1 * auto-generated via 'PrintFunctionOptimalExp.py' * Detailed description: @@ -657,6 +695,8 @@ contract BancorFormula { * - The exponentiation of r is calculated via Taylor series for e^x, where x = r * - The exponentiation of the input is calculated by multiplying the intermediate results above * - For example: e^5.521692859 = e^(4 + 1 + 0.5 + 0.021692859) = e^4 * e^1 * e^0.5 * e^0.021692859 + * @param x The input value + * @return The computed exponential result */ function optimalExp(uint256 x) internal pure returns (uint256) { uint256 res = 0; @@ -724,7 +764,13 @@ contract BancorFormula { } /** - * @dev deprecated, backward compatibility + * @notice Deprecated function for backward compatibility + * @param _fromConnectorBalance input connector balance + * @param _fromConnectorWeight input connector weight + * @param _toConnectorBalance output connector balance + * @param _toConnectorWeight output connector weight + * @param _amount input connector amount + * @return output connector amount */ function calculateCrossConnectorReturn( uint256 _fromConnectorBalance, diff --git a/packages/contracts/contracts/base/IMulticall.sol b/packages/contracts/contracts/base/IMulticall.sol deleted file mode 100644 index 10f7fa469..000000000 --- a/packages/contracts/contracts/base/IMulticall.sol +++ /dev/null @@ -1,17 +0,0 @@ -// 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); -} diff --git a/packages/contracts/contracts/base/Multicall.sol b/packages/contracts/contracts/base/Multicall.sol index 49111840d..808f7695f 100644 --- a/packages/contracts/contracts/base/Multicall.sol +++ b/packages/contracts/contracts/base/Multicall.sol @@ -3,13 +3,17 @@ pragma solidity ^0.7.6; pragma abicoder v2; -import "./IMulticall.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-increment-by-one + +import { IMulticall } from "@graphprotocol/interfaces/contracts/contracts/base/IMulticall.sol"; // Inspired by https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/base/Multicall.sol // Note: Removed payable from the multicall /** * @title Multicall + * @author Edge & Node * @notice Enables calling multiple methods in a single call to the contract */ abstract contract Multicall is IMulticall { @@ -17,11 +21,12 @@ abstract contract Multicall is IMulticall { function multicall(bytes[] calldata data) external override returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { - (bool success, bytes memory result) = address(this).delegatecall(data[i]); + (bool success, bytes memory result) = address(this).delegatecall(data[i]); // solhint-disable-line avoid-low-level-calls if (!success) { // Next 5 lines from https://ethereum.stackexchange.com/a/83577 if (result.length < 68) revert(); + // solhint-disable-next-line no-inline-assembly assembly { result := add(result, 0x04) } diff --git a/packages/contracts/contracts/curation/Curation.sol b/packages/contracts/contracts/curation/Curation.sol index 827c230b7..e7aac2cc2 100644 --- a/packages/contracts/contracts/curation/Curation.sol +++ b/packages/contracts/contracts/curation/Curation.sol @@ -3,6 +3,9 @@ pragma solidity ^0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events, gas-small-strings, gas-strict-inequalities + import { AddressUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import { SafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import { ClonesUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/ClonesUpgradeable.sol"; @@ -10,15 +13,16 @@ import { ClonesUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/Clo import { BancorFormula } from "../bancor/BancorFormula.sol"; import { GraphUpgradeable } from "../upgrades/GraphUpgradeable.sol"; import { TokenUtils } from "../utils/TokenUtils.sol"; -import { IRewardsManager } from "../rewards/IRewardsManager.sol"; +import { IRewardsManager } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsManager.sol"; import { Managed } from "../governance/Managed.sol"; -import { IGraphToken } from "../token/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { CurationV2Storage } from "./CurationStorage.sol"; -import { IGraphCurationToken } from "./IGraphCurationToken.sol"; +import { IGraphCurationToken } from "@graphprotocol/interfaces/contracts/contracts/curation/IGraphCurationToken.sol"; /** * @title Curation contract - * @dev Allows curators to signal on subgraph deployments that might be relevant to indexers by + * @author Edge & Node + * @notice Allows curators to signal on subgraph deployments that might be relevant to indexers by * staking Graph Tokens (GRT). Additionally, curators earn fees from the Query Market related to the * subgraph deployment they curate. * A curators deposit goes to a curation pool along with the deposits of other curators, @@ -40,9 +44,14 @@ contract Curation is CurationV2Storage, GraphUpgradeable { // -- Events -- /** - * @dev Emitted when `curator` deposited `tokens` on `subgraphDeploymentID` as curation signal. + * @notice Emitted when `curator` deposited `tokens` on `subgraphDeploymentID` as curation signal. * The `curator` receives `signal` amount according to the curation pool bonding curve. * An amount of `curationTax` will be collected and burned. + * @param curator Address of the curator + * @param subgraphDeploymentID Subgraph deployment being signaled on + * @param tokens Amount of tokens deposited + * @param signal Amount of signal minted + * @param curationTax Amount of tokens burned as curation tax */ event Signalled( address indexed curator, @@ -53,14 +62,20 @@ contract Curation is CurationV2Storage, GraphUpgradeable { ); /** - * @dev Emitted when `curator` burned `signal` for a `subgraphDeploymentID`. + * @notice Emitted when `curator` burned `signal` for a `subgraphDeploymentID`. * The curator will receive `tokens` according to the value of the bonding curve. + * @param curator Address of the curator + * @param subgraphDeploymentID Subgraph deployment being signaled on + * @param tokens Amount of tokens received + * @param signal Amount of signal burned */ event Burned(address indexed curator, bytes32 indexed subgraphDeploymentID, uint256 tokens, uint256 signal); /** - * @dev Emitted when `tokens` amount were collected for `subgraphDeploymentID` as part of fees + * @notice Emitted when `tokens` amount were collected for `subgraphDeploymentID` as part of fees * distributed by an indexer from query fees received from state channels. + * @param subgraphDeploymentID Subgraph deployment that collected fees + * @param tokens Amount of tokens collected as fees */ event Collected(bytes32 indexed subgraphDeploymentID, uint256 tokens); @@ -94,8 +109,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { } /** - * @dev Set the default reserve ratio percentage for a curation pool. - * @notice Update the default reserve ratio to `_defaultReserveRatio` + * @notice Set the default reserve ratio percentage for a curation pool. * @param _defaultReserveRatio Reserve ratio (in PPM) */ function setDefaultReserveRatio(uint32 _defaultReserveRatio) external override onlyGovernor { @@ -103,8 +117,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { } /** - * @dev Set the minimum deposit amount for curators. - * @notice Update the minimum deposit amount to `_minimumCurationDeposit` + * @notice Set the minimum deposit amount for curators. * @param _minimumCurationDeposit Minimum amount of tokens required deposit */ function setMinimumCurationDeposit(uint256 _minimumCurationDeposit) external override onlyGovernor { @@ -207,7 +220,6 @@ contract Curation is CurationV2Storage, GraphUpgradeable { } /** - * @dev Return an amount of signal to get tokens back. * @notice Burn _signal from the SubgraphDeployment curation pool * @param _subgraphDeploymentID SubgraphDeployment the curator is returning signal * @param _signalIn Amount of signal to return @@ -313,7 +325,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { } /** - * @dev Calculate amount of signal that can be bought with tokens in a curation pool. + * @notice Calculate amount of signal that can be bought with tokens in a curation pool. * @param _subgraphDeploymentID Subgraph deployment to mint signal * @param _tokensIn Amount of tokens used to mint signal * @return Amount of signal that can be bought with tokens @@ -367,7 +379,6 @@ contract Curation is CurationV2Storage, GraphUpgradeable { } /** - * @dev Internal: Set the default reserve ratio percentage for a curation pool. * @notice Update the default reserver ratio to `_defaultReserveRatio` * @param _defaultReserveRatio Reserve ratio (in PPM) */ @@ -381,7 +392,6 @@ contract Curation is CurationV2Storage, GraphUpgradeable { } /** - * @dev Internal: Set the minimum deposit amount for curators. * @notice Update the minimum deposit amount to `_minimumCurationDeposit` * @param _minimumCurationDeposit Minimum amount of tokens required deposit */ @@ -393,7 +403,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { } /** - * @dev Internal: Set the curation tax percentage (in PPM) to charge when a curator deposits GRT tokens. + * @notice Internal: Set the curation tax percentage (in PPM) to charge when a curator deposits GRT tokens. * @param _percentage Curation tax charged when depositing GRT tokens in PPM */ function _setCurationTaxPercentage(uint32 _percentage) private { @@ -404,7 +414,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { } /** - * @dev Internal: Set the master copy to use as clones for the curation token. + * @notice Internal: 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) private { @@ -416,7 +426,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { } /** - * @dev Triggers an update of rewards due to a change in signal. + * @notice Triggers an update of rewards due to a change in signal. * @param _subgraphDeploymentID Subgraph deployment updated */ function _updateRewards(bytes32 _subgraphDeploymentID) private { diff --git a/packages/contracts/contracts/curation/CurationStorage.sol b/packages/contracts/contracts/curation/CurationStorage.sol index 12f5b255b..67b302bfe 100644 --- a/packages/contracts/contracts/curation/CurationStorage.sol +++ b/packages/contracts/contracts/curation/CurationStorage.sol @@ -1,16 +1,21 @@ // SPDX-License-Identifier: GPL-2.0-or-later +// solhint-disable one-contract-per-file pragma solidity ^0.7.6; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable named-parameters-mapping + import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol"; -import { ICuration } from "./ICuration.sol"; -import { IGraphCurationToken } from "./IGraphCurationToken.sol"; +import { ICuration } from "@graphprotocol/interfaces/contracts/contracts/curation/ICuration.sol"; +import { IGraphCurationToken } from "@graphprotocol/interfaces/contracts/contracts/curation/IGraphCurationToken.sol"; import { Managed } from "../governance/Managed.sol"; /** * @title Curation Storage version 1 - * @dev This contract holds the first version of the storage variables + * @author Edge & Node + * @notice This contract holds the first version of the storage variables * for the Curation and L2Curation contracts. * When adding new variables, create a new version that inherits this and update * the contracts to use the new version instead. @@ -21,6 +26,9 @@ abstract contract CurationV1Storage is Managed, ICuration { /** * @dev CurationPool structure that holds the pool's state * for a particular subgraph deployment. + * @param tokens GRT Tokens stored as reserves for the subgraph deployment + * @param reserveRatio Ratio for the bonding curve, unused and deprecated in L2 where it will always be 100% but appear as 0 + * @param gcs Curation token contract for this curation pool */ struct CurationPool { uint256 tokens; // GRT Tokens stored as reserves for the subgraph deployment @@ -30,35 +38,36 @@ abstract contract CurationV1Storage is Managed, ICuration { // -- State -- - /// Tax charged when curators deposit funds. + /// @notice Tax charged when curators deposit funds. /// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%) uint32 public override curationTaxPercentage; - /// Default reserve ratio to configure curator shares bonding curve + /// @notice Default reserve ratio to configure curator shares bonding curve /// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%). /// Unused in L2. uint32 public defaultReserveRatio; - /// Master copy address that holds implementation of curation token. + /// @notice Master copy address that holds implementation of curation token. /// @dev This is used as the target for GraphCurationToken clones. address public curationTokenMaster; - /// Minimum amount allowed to be deposited by curators to initialize a pool + /// @notice Minimum amount allowed to be deposited by curators to initialize a pool /// @dev This is the `startPoolBalance` for the bonding curve uint256 public minimumCurationDeposit; - /// Bonding curve library + /// @notice Bonding curve library /// Unused in L2. address public bondingCurve; - /// @dev Mapping of subgraphDeploymentID => CurationPool + /// @notice Mapping of subgraphDeploymentID => CurationPool /// There is only one CurationPool per SubgraphDeploymentID mapping(bytes32 => CurationPool) public pools; } /** * @title Curation Storage version 2 - * @dev This contract holds the second version of the storage variables + * @author Edge & Node + * @notice This contract holds the second version of the storage variables * for the Curation and L2Curation contracts. * It doesn't add new variables at this contract's level, but adds the Initializable * contract to the inheritance chain, which includes storage variables. @@ -71,6 +80,8 @@ abstract contract CurationV2Storage is CurationV1Storage, Initializable { /** * @title Curation Storage version 3 + * @author Edge & Node + * @notice This contract holds the third version of the storage variables for the Curation and L2Curation contracts * @dev This contract holds the third version of the storage variables * for the Curation and L2Curation contracts. * It adds a new variable subgraphService to the storage. @@ -78,6 +89,6 @@ abstract contract CurationV2Storage is CurationV1Storage, Initializable { * the contracts to use the new version instead. */ abstract contract CurationV3Storage is CurationV2Storage { - // Address of the subgraph service + /// @notice Address of the subgraph service address public subgraphService; } diff --git a/packages/contracts/contracts/curation/GraphCurationToken.sol b/packages/contracts/contracts/curation/GraphCurationToken.sol index 78b721e1b..108cc0680 100644 --- a/packages/contracts/contracts/curation/GraphCurationToken.sol +++ b/packages/contracts/contracts/curation/GraphCurationToken.sol @@ -2,13 +2,14 @@ pragma solidity ^0.7.6; -import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; +import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; -import "../governance/Governed.sol"; +import { Governed } from "../governance/Governed.sol"; /** * @title GraphCurationToken contract - * @dev This is the implementation of the Curation ERC20 token (GCS). + * @author Edge & Node + * @notice This is the implementation of the Curation ERC20 token (GCS). * * GCS are created for each subgraph deployment curated in the Curation contract. * The Curation contract is the owner of GCS tokens and the only one allowed to mint or @@ -20,7 +21,7 @@ import "../governance/Governed.sol"; */ contract GraphCurationToken is ERC20Upgradeable, Governed { /** - * @dev Graph Curation Token Contract initializer. + * @notice Graph Curation Token Contract initializer. * @param _owner Address of the contract issuing this token */ function initialize(address _owner) external initializer { @@ -29,7 +30,7 @@ contract GraphCurationToken is ERC20Upgradeable, Governed { } /** - * @dev Mint new tokens. + * @notice Mint new tokens. * @param _to Address to send the newly minted tokens * @param _amount Amount of tokens to mint */ @@ -38,7 +39,7 @@ contract GraphCurationToken is ERC20Upgradeable, Governed { } /** - * @dev Burn tokens from an address. + * @notice Burn tokens from an address. * @param _account Address from where tokens will be burned * @param _amount Amount of tokens to burn */ diff --git a/packages/contracts/contracts/curation/ICuration.sol b/packages/contracts/contracts/curation/ICuration.sol deleted file mode 100644 index 4f2c2bac5..000000000 --- a/packages/contracts/contracts/curation/ICuration.sol +++ /dev/null @@ -1,123 +0,0 @@ -// 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); -} diff --git a/packages/contracts/contracts/curation/IGraphCurationToken.sol b/packages/contracts/contracts/curation/IGraphCurationToken.sol deleted file mode 100644 index 43679aba6..000000000 --- a/packages/contracts/contracts/curation/IGraphCurationToken.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity ^0.7.6; - -import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; - -interface IGraphCurationToken is IERC20Upgradeable { - function initialize(address _owner) external; - - function burnFrom(address _account, uint256 _amount) external; - - function mint(address _to, uint256 _amount) external; -} diff --git a/packages/contracts/contracts/discovery/GNS.sol b/packages/contracts/contracts/discovery/GNS.sol index 3cbb9ca8a..384bd3b66 100644 --- a/packages/contracts/contracts/discovery/GNS.sol +++ b/packages/contracts/contracts/discovery/GNS.sol @@ -3,22 +3,26 @@ pragma solidity ^0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable function-max-lines, gas-indexed-events, gas-small-strings, gas-strict-inequalities + import { SafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import { AddressUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import { Multicall } from "../base/Multicall.sol"; import { GraphUpgradeable } from "../upgrades/GraphUpgradeable.sol"; import { TokenUtils } from "../utils/TokenUtils.sol"; -import { ICuration } from "../curation/ICuration.sol"; +import { ICuration } from "@graphprotocol/interfaces/contracts/contracts/curation/ICuration.sol"; import { Managed } from "../governance/Managed.sol"; -import { ISubgraphNFT } from "./ISubgraphNFT.sol"; +import { ISubgraphNFT } from "@graphprotocol/interfaces/contracts/contracts/discovery/ISubgraphNFT.sol"; -import { IGNS } from "./IGNS.sol"; +import { IGNS } from "@graphprotocol/interfaces/contracts/contracts/discovery/IGNS.sol"; import { GNSV3Storage } from "./GNSStorage.sol"; /** * @title GNS - * @dev The Graph Name System contract provides a decentralized naming system for subgraphs + * @author Edge & Node + * @notice The Graph Name System contract provides a decentralized naming system for subgraphs * used in the scope of the Graph Network. It translates Subgraphs into Subgraph Versions. * Each version is associated with a Subgraph Deployment. The contract has no knowledge of * human-readable names. All human readable names emitted in events. @@ -34,15 +38,21 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { uint32 private constant MAX_PPM = 1000000; /// @dev Equates to Connector weight on bancor formula to be CW = 1 + // solhint-disable-next-line immutable-vars-naming uint32 internal immutable fixedReserveRatio = MAX_PPM; // -- Events -- - /// @dev Emitted when the subgraph NFT contract is updated + /// @notice Emitted when the subgraph NFT contract is updated + /// @param subgraphNFT Address of the new subgraph NFT contract event SubgraphNFTUpdated(address subgraphNFT); /** - * @dev Emitted when graph account sets its default name + * @notice Emitted when graph account sets its default name + * @param graphAccount Address of the graph account + * @param nameSystem Name system identifier (only ENS for now) + * @param nameIdentifier Name identifier in the name system + * @param name Human-readable name */ event SetDefaultName( address indexed graphAccount, @@ -52,12 +62,17 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { ); /** - * @dev Emitted when the subgraph metadata is updated. + * @notice Emitted when the subgraph metadata is updated. + * @param subgraphID ID of the subgraph + * @param subgraphMetadata IPFS hash of the subgraph metadata */ event SubgraphMetadataUpdated(uint256 indexed subgraphID, bytes32 subgraphMetadata); /** - * @dev Emitted when a subgraph version is updated. + * @notice Emitted when a subgraph version is updated. + * @param subgraphID ID of the subgraph + * @param subgraphDeploymentID Subgraph deployment ID for the new version + * @param versionMetadata IPFS hash of the version metadata */ event SubgraphVersionUpdated( uint256 indexed subgraphID, @@ -66,7 +81,12 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { ); /** - * @dev Emitted when a curator mints signal. + * @notice Emitted when a curator mints signal. + * @param subgraphID ID of the subgraph + * @param curator Address of the curator + * @param nSignalCreated Amount of name signal created + * @param vSignalCreated Amount of version signal created + * @param tokensDeposited Amount of tokens deposited */ event SignalMinted( uint256 indexed subgraphID, @@ -77,7 +97,12 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { ); /** - * @dev Emitted when a curator burns signal. + * @notice Emitted when a curator burns signal. + * @param subgraphID ID of the subgraph + * @param curator Address of the curator + * @param nSignalBurnt Amount of name signal burned + * @param vSignalBurnt Amount of version signal burned + * @param tokensReceived Amount of tokens received */ event SignalBurned( uint256 indexed subgraphID, @@ -88,7 +113,11 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { ); /** - * @dev Emitted when a curator transfers signal. + * @notice Emitted when a curator transfers signal. + * @param subgraphID ID of the subgraph + * @param from Address transferring the signal + * @param to Address receiving the signal + * @param nSignalTransferred Amount of name signal transferred */ event SignalTransferred( uint256 indexed subgraphID, @@ -98,14 +127,21 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { ); /** - * @dev Emitted when a subgraph is created. + * @notice Emitted when a subgraph is created. + * @param subgraphID ID of the subgraph + * @param subgraphDeploymentID Subgraph deployment ID + * @param reserveRatio Reserve ratio for the bonding curve */ event SubgraphPublished(uint256 indexed subgraphID, bytes32 indexed subgraphDeploymentID, uint32 reserveRatio); /** - * @dev Emitted when a subgraph is upgraded to point to a new + * @notice Emitted when a subgraph is upgraded to point to a new * subgraph deployment, burning all the old vSignal and depositing the GRT into the * new vSignal curve. + * @param subgraphID ID of the subgraph + * @param vSignalCreated Amount of version signal created in the new deployment + * @param tokensSignalled Amount of tokens signalled in the new deployment + * @param subgraphDeploymentID New subgraph deployment ID */ event SubgraphUpgraded( uint256 indexed subgraphID, @@ -115,29 +151,39 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { ); /** - * @dev Emitted when a subgraph is deprecated. + * @notice Emitted when a subgraph is deprecated. + * @param subgraphID ID of the subgraph + * @param withdrawableGRT Amount of GRT available for withdrawal */ event SubgraphDeprecated(uint256 indexed subgraphID, uint256 withdrawableGRT); /** - * @dev Emitted when a curator withdraws GRT from a deprecated subgraph + * @notice Emitted when a curator withdraws GRT from a deprecated subgraph + * @param subgraphID ID of the subgraph + * @param curator Address of the curator + * @param nSignalBurnt Amount of name signal burned + * @param withdrawnGRT Amount of GRT withdrawn */ event GRTWithdrawn(uint256 indexed subgraphID, address indexed curator, uint256 nSignalBurnt, uint256 withdrawnGRT); /** - * @dev Emitted when the counterpart (L1/L2) GNS address is updated + * @notice Emitted when the counterpart (L1/L2) GNS address is updated + * @param _counterpart Address of the counterpart GNS contract */ event CounterpartGNSAddressUpdated(address _counterpart); // -- Modifiers -- /** - * @dev Emitted when a legacy subgraph is claimed + * @notice Emitted when a legacy subgraph is claimed + * @param graphAccount Address of the graph account that created the subgraph + * @param subgraphNumber Sequence number of the subgraph */ event LegacySubgraphClaimed(address indexed graphAccount, uint256 subgraphNumber); /** - * @dev Modifier that allows only a subgraph operator to be the caller + * @notice Modifier that allows only a subgraph operator to be the caller + * @param _subgraphID ID of the subgraph to check authorization for */ modifier onlySubgraphAuth(uint256 _subgraphID) { require(ownerOf(_subgraphID) == msg.sender, "GNS: Must be authorized"); @@ -160,7 +206,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @notice Approve curation contract to pull funds. + * @inheritdoc IGNS */ function approveAll() external override { graphToken().approve(address(curation()), type(uint256).max); @@ -169,9 +215,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { // -- Config -- /** - * @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 + * @inheritdoc IGNS */ function setOwnerTaxPercentage(uint32 _ownerTaxPercentage) external override onlyGovernor { _setOwnerTaxPercentage(_ownerTaxPercentage); @@ -200,11 +244,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { // -- Actions -- /** - * @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 + * @inheritdoc IGNS */ function setDefaultName( address _graphAccount, @@ -217,9 +257,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @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 + * @inheritdoc IGNS */ function updateSubgraphMetadata( uint256 _subgraphID, @@ -229,10 +267,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @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 + * @inheritdoc IGNS */ function publishNewSubgraph( bytes32 _subgraphDeploymentID, @@ -261,10 +296,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @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 + * @inheritdoc IGNS */ function publishNewVersion( uint256 _subgraphID, @@ -322,10 +354,10 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @notice Deprecate a subgraph. The bonding curve is destroyed, the vSignal is burned, and the GNS + * @inheritdoc IGNS + * @notice 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 override notPaused onlySubgraphAuth(_subgraphID) { // Subgraph check @@ -350,10 +382,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @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 + * @inheritdoc IGNS */ function mintSignal( uint256 _subgraphID, @@ -383,10 +412,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @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 + * @inheritdoc IGNS */ function burnSignal( uint256 _subgraphID, @@ -543,7 +569,9 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * @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 + * @return nSignalOut Amount of name signal minted + * @return curationTax Amount of curation tax charged + * @return vSignalOut Amount of version signal minted */ function tokensToNSignal( uint256 _subgraphID, @@ -562,7 +590,8 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * @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 + * @return vSignalOut Amount of version signal burned + * @return tokensOut Amount of tokens returned */ function nSignalToTokens(uint256 _subgraphID, uint256 _nSignalIn) public view override returns (uint256, uint256) { // Get subgraph or revert if not published @@ -574,10 +603,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @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 + * @inheritdoc IGNS */ function vSignalToNSignal(uint256 _subgraphID, uint256 _vSignalIn) public view override returns (uint256) { SubgraphData storage subgraphData = _getSubgraphData(_subgraphID); @@ -591,10 +617,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @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 + * @inheritdoc IGNS */ function nSignalToVSignal(uint256 _subgraphID, uint256 _nSignalIn) public view override returns (uint256) { SubgraphData storage subgraphData = _getSubgraphData(_subgraphID); @@ -602,29 +625,21 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @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 + * @inheritdoc IGNS */ function getCuratorSignal(uint256 _subgraphID, address _curator) public view override returns (uint256) { return _getSubgraphData(_subgraphID).curatorNSignal[_curator]; } /** - * @notice Return whether a subgraph is published. - * @param _subgraphID Subgraph ID - * @return Return true if subgraph is currently published + * @inheritdoc IGNS */ function isPublished(uint256 _subgraphID) public view override returns (bool) { return _isPublished(_getSubgraphData(_subgraphID)); } /** - * @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 + * @inheritdoc IGNS */ function getLegacySubgraphKey(uint256 _subgraphID) public view override returns (address account, uint256 seqID) { LegacySubgraphKey storage legacySubgraphKey = legacySubgraphKeys[_subgraphID]; @@ -633,16 +648,14 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @notice Return the owner of a subgraph. - * @param _tokenID Subgraph ID - * @return Owner address + * @inheritdoc IGNS */ function ownerOf(uint256 _tokenID) public view override returns (address) { return subgraphNFT.ownerOf(_tokenID); } /** - * @dev Calculate tax that owner will have to cover for upgrading or deprecating. + * @notice Calculate tax that owner will have to cover for upgrading or deprecating. * @param _tokens Tokens that were received from deprecating the old subgraph * @param _owner Subgraph owner * @param _curationTaxPercentage Tax percentage on curation deposits from Curation contract @@ -689,8 +702,9 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @dev Return the next subgraphID given the account that is creating the subgraph. + * @notice Return the next subgraphID given the account that is creating the subgraph. * NOTE: This function updates the sequence ID for the account + * @param _account The account creating the subgraph * @return Sequence ID for the account */ function _nextSubgraphID(address _account) internal returns (uint256) { @@ -698,8 +712,9 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @dev Return a new consecutive sequence ID for an account and update to the next value. + * @notice Return a new consecutive sequence ID for an account and update to the next value. * NOTE: This function updates the sequence ID for the account + * @param _account The account to get the next sequence ID for * @return Sequence ID for the account */ function _nextAccountSeqID(address _account) internal returns (uint256) { @@ -709,7 +724,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @dev Mint the NFT for the subgraph. + * @notice Mint the NFT for the subgraph. * @param _owner Owner address * @param _tokenID Subgraph ID */ @@ -718,7 +733,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @dev Burn the NFT for the subgraph. + * @notice Burn the NFT for the subgraph. * @param _tokenID Subgraph ID */ function _burnNFT(uint256 _tokenID) internal { @@ -726,7 +741,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @dev Set the subgraph metadata. + * @notice Set the subgraph metadata. * @param _tokenID Subgraph ID * @param _subgraphMetadata IPFS hash of the subgraph metadata */ @@ -739,7 +754,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @dev Get subgraph data. + * @notice Get subgraph data. * This function will first look for a v1 subgraph and return it if found. * @param _subgraphID Subgraph ID * @return Subgraph Data @@ -755,7 +770,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @dev Return whether a subgraph is published. + * @notice Return whether a subgraph is published. * @param _subgraphData Subgraph Data * @return Return true if subgraph is currently published */ @@ -764,7 +779,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @dev Return the subgraph data or revert if not published or deprecated. + * @notice Return the subgraph data or revert if not published or deprecated. * @param _subgraphID Subgraph ID * @return Subgraph Data */ @@ -775,9 +790,11 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @dev Build a subgraph ID based on the account creating it and a sequence number for that account. + * @notice Build a subgraph ID based on the account creating it and a sequence number for that account. * Only used for legacy subgraphs being migrated, as new ones will also use the chainid. * Subgraph ID is the keccak hash of account+seqID + * @param _account The account creating the subgraph + * @param _seqID The sequence ID for the account * @return Subgraph ID */ function _buildLegacySubgraphID(address _account, uint256 _seqID) internal pure returns (uint256) { @@ -785,8 +802,10 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @dev Build a subgraph ID based on the account creating it and a sequence number for that account. + * @notice Build a subgraph ID based on the account creating it and a sequence number for that account. * Subgraph ID is the keccak hash of account+seqID + * @param _account The account creating the subgraph + * @param _seqID The sequence ID for the account * @return Subgraph ID */ function _buildSubgraphID(address _account, uint256 _seqID) internal pure returns (uint256) { @@ -800,7 +819,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @dev Internal: Set the owner tax percentage. This is used to prevent a subgraph owner to drain all + * @notice Internal: Set the owner tax 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 */ @@ -811,7 +830,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { } /** - * @dev Internal: Set the NFT registry contract + * @notice Internal: Set the NFT registry contract * @param _subgraphNFT Address of the ERC721 contract */ function _setSubgraphNFT(address _subgraphNFT) private { diff --git a/packages/contracts/contracts/discovery/GNSStorage.sol b/packages/contracts/contracts/discovery/GNSStorage.sol index 80122c9ba..ca746ec29 100644 --- a/packages/contracts/contracts/discovery/GNSStorage.sol +++ b/packages/contracts/contracts/discovery/GNSStorage.sol @@ -1,23 +1,28 @@ // SPDX-License-Identifier: GPL-2.0-or-later +// solhint-disable one-contract-per-file pragma solidity ^0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable named-parameters-mapping + import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol"; import { Managed } from "../governance/Managed.sol"; -import { IEthereumDIDRegistry } from "./erc1056/IEthereumDIDRegistry.sol"; -import { IGNS } from "./IGNS.sol"; -import { ISubgraphNFT } from "./ISubgraphNFT.sol"; +import { IEthereumDIDRegistry } from "@graphprotocol/interfaces/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol"; +import { IGNS } from "@graphprotocol/interfaces/contracts/contracts/discovery/IGNS.sol"; +import { ISubgraphNFT } from "@graphprotocol/interfaces/contracts/contracts/discovery/ISubgraphNFT.sol"; /** * @title GNSV1Storage + * @author Edge & Node * @notice This contract holds all the storage variables for the GNS contract, version 1 */ abstract contract GNSV1Storage is Managed { // -- State -- - /// Percentage of curation tax that must be paid by the owner, in parts per million. + /// @notice Percentage of curation tax that must be paid by the owner, in parts per million. uint32 public ownerTaxPercentage; /// @dev [DEPRECATED] Bonding curve formula. @@ -29,11 +34,11 @@ abstract contract GNSV1Storage is Managed { /// (graphAccountID, subgraphNumber) => subgraphDeploymentID mapping(address => mapping(uint256 => bytes32)) internal legacySubgraphs; - /// Every time an account creates a subgraph it increases a per-account sequence ID. + /// @notice Every time an account creates a subgraph it increases a per-account sequence ID. /// account => seqID mapping(address => uint256) public nextAccountSeqID; - /// Stores all the signal deposited on a legacy subgraph. + /// @notice Stores all the signal deposited on a legacy subgraph. /// (graphAccountID, subgraphNumber) => SubgraphData mapping(address => mapping(uint256 => IGNS.SubgraphData)) public legacySubgraphData; @@ -44,31 +49,33 @@ abstract contract GNSV1Storage is Managed { /** * @title GNSV2Storage + * @author Edge & Node * @notice This contract holds all the storage variables for the GNS contract, version 2 */ abstract contract GNSV2Storage is GNSV1Storage { - /// Stores the account and seqID for a legacy subgraph that has been migrated. + /// @notice Stores the account and seqID for a legacy subgraph that has been migrated. /// Use it whenever a legacy (v1) subgraph NFT was claimed to maintain compatibility. /// Keep a reference from subgraphID => (graphAccount, subgraphNumber) mapping(uint256 => IGNS.LegacySubgraphKey) public legacySubgraphKeys; - /// Store data for all NFT-based (v2) subgraphs. + /// @notice Store data for all NFT-based (v2) subgraphs. /// subgraphID => SubgraphData mapping(uint256 => IGNS.SubgraphData) public subgraphs; - /// Contract that represents subgraph ownership through an NFT + /// @notice Contract that represents subgraph ownership through an NFT ISubgraphNFT public subgraphNFT; } /** * @title GNSV3Storage + * @author Edge & Node * @notice This contract holds all the storage variables for the base GNS contract, version 3. * @dev Note that this is the first version that includes a storage gap - if adding * future versions, make sure to move the gap to the new version and * reduce the size of the gap accordingly. */ abstract contract GNSV3Storage is GNSV2Storage, Initializable { - /// Address of the counterpart GNS contract (L1GNS/L2GNS) + /// @notice Address of the counterpart GNS contract (L1GNS/L2GNS) address public counterpartGNSAddress; /// @dev Gap to allow adding variables in future upgrades (since L1GNS and L2GNS have their own storage as well) uint256[50] private __gap; diff --git a/packages/contracts/contracts/discovery/IGNS.sol b/packages/contracts/contracts/discovery/IGNS.sol deleted file mode 100644 index 70b366d9b..000000000 --- a/packages/contracts/contracts/discovery/IGNS.sol +++ /dev/null @@ -1,218 +0,0 @@ -// 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); -} diff --git a/packages/contracts/contracts/discovery/IServiceRegistry.sol b/packages/contracts/contracts/discovery/IServiceRegistry.sol deleted file mode 100644 index 724f7bebe..000000000 --- a/packages/contracts/contracts/discovery/IServiceRegistry.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity ^0.7.6 || 0.8.27; - -interface IServiceRegistry { - struct IndexerService { - string url; - string geohash; - } - - function register(string calldata _url, string calldata _geohash) external; - - function registerFor(address _indexer, string calldata _url, string calldata _geohash) external; - - function unregister() external; - - function unregisterFor(address _indexer) external; - - function isRegistered(address _indexer) external view returns (bool); -} diff --git a/packages/contracts/contracts/discovery/ISubgraphNFT.sol b/packages/contracts/contracts/discovery/ISubgraphNFT.sol deleted file mode 100644 index 6cef69297..000000000 --- a/packages/contracts/contracts/discovery/ISubgraphNFT.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity ^0.7.6 || 0.8.27; - -import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; - -interface ISubgraphNFT is IERC721 { - // -- Config -- - - function setMinter(address _minter) external; - - function setTokenDescriptor(address _tokenDescriptor) external; - - function setBaseURI(string memory _baseURI) external; - - // -- Actions -- - - function mint(address _to, uint256 _tokenId) external; - - function burn(uint256 _tokenId) external; - - function setSubgraphMetadata(uint256 _tokenId, bytes32 _subgraphMetadata) external; - - function tokenURI(uint256 _tokenId) external view returns (string memory); -} diff --git a/packages/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol b/packages/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol deleted file mode 100644 index cd0785dcb..000000000 --- a/packages/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity ^0.7.6; - -/// @title Describes subgraph NFT tokens via URI -interface ISubgraphNFTDescriptor { - /// @notice Produces the URI describing a particular token ID for a Subgraph - /// @dev Note this URI may be data: URI with the JSON contents directly inlined - /// @param _minter Address of the allowed minter - /// @param _tokenId The ID of the subgraph NFT for which to produce a description, which may not be valid - /// @param _baseURI The base URI that could be prefixed to the final URI - /// @param _subgraphMetadata Subgraph metadata set for the subgraph - /// @return The URI of the ERC721-compliant metadata - function tokenURI( - address _minter, - uint256 _tokenId, - string calldata _baseURI, - bytes32 _subgraphMetadata - ) external view returns (string memory); -} diff --git a/packages/contracts/contracts/discovery/L1GNS.sol b/packages/contracts/contracts/discovery/L1GNS.sol index 31e9b0fb3..3441d05fa 100644 --- a/packages/contracts/contracts/discovery/L1GNS.sol +++ b/packages/contracts/contracts/discovery/L1GNS.sol @@ -7,14 +7,15 @@ import { SafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/Sa import { GNS } from "./GNS.sol"; -import { ITokenGateway } from "../arbitrum/ITokenGateway.sol"; -import { IL2GNS } from "../l2/discovery/IL2GNS.sol"; -import { IGraphToken } from "../token/IGraphToken.sol"; +import { ITokenGateway } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol"; +import { IL2GNS } from "@graphprotocol/interfaces/contracts/contracts/l2/discovery/IL2GNS.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { L1GNSV1Storage } from "./L1GNSStorage.sol"; /** * @title L1GNS - * @dev The Graph Name System contract provides a decentralized naming system for subgraphs + * @author Edge & Node + * @notice The Graph Name System contract provides a decentralized naming system for subgraphs * used in the scope of the Graph Network. It translates Subgraphs into Subgraph Versions. * Each version is associated with a Subgraph Deployment. The contract has no knowledge of * human-readable names. All human readable names emitted in events. @@ -25,7 +26,13 @@ import { L1GNSV1Storage } from "./L1GNSStorage.sol"; contract L1GNS is GNS, L1GNSV1Storage { using SafeMathUpgradeable for uint256; - /// @dev Emitted when a subgraph was sent to L2 through the bridge + /** + * @notice Emitted when a subgraph was sent to L2 through the bridge + * @param _subgraphID ID of the subgraph being transferred + * @param _l1Owner Address of the subgraph owner on L1 + * @param _l2Owner Address that will own the subgraph on L2 + * @param _tokens Amount of tokens transferred with the subgraph + */ event SubgraphSentToL2( uint256 indexed _subgraphID, address indexed _l1Owner, @@ -33,7 +40,13 @@ contract L1GNS is GNS, L1GNSV1Storage { uint256 _tokens ); - /// @dev Emitted when a curator's balance for a subgraph was sent to L2 + /** + * @notice Emitted when a curator's balance for a subgraph was sent to L2 + * @param _subgraphID ID of the subgraph + * @param _l1Curator Address of the curator on L1 + * @param _l2Beneficiary Address that will receive the tokens on L2 + * @param _tokens Amount of tokens transferred + */ event CuratorBalanceSentToL2( uint256 indexed _subgraphID, address indexed _l1Curator, @@ -42,10 +55,10 @@ contract L1GNS is GNS, L1GNSV1Storage { ); /** - * @notice Send a subgraph's data and tokens to L2. - * Use the Arbitrum SDK to estimate the L2 retryable ticket parameters. + * @notice Send a subgraph's data and tokens to L2 + * @dev Use the Arbitrum SDK to estimate the L2 retryable ticket parameters. * Note that any L2 gas/fee refunds will be lost, so the function only accepts - * the exact amount of ETH to cover _maxSubmissionCost + _maxGas * _gasPriceBid. + * the exact amount of ETH to cover _maxSubmissionCost + _maxGas * _gasPriceBid * @param _subgraphID Subgraph ID * @param _l2Owner Address that will own the subgraph in L2 (could be the L1 owner, but could be different if the L1 owner is an L1 contract) * @param _maxGas Max gas to use for the L2 retryable ticket diff --git a/packages/contracts/contracts/discovery/L1GNSStorage.sol b/packages/contracts/contracts/discovery/L1GNSStorage.sol index 557814513..72af676f2 100644 --- a/packages/contracts/contracts/discovery/L1GNSStorage.sol +++ b/packages/contracts/contracts/discovery/L1GNSStorage.sol @@ -1,16 +1,20 @@ // SPDX-License-Identifier: GPL-2.0-or-later +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable named-parameters-mapping + pragma solidity ^0.7.6; pragma abicoder v2; /** * @title L1GNSV1Storage + * @author Edge & Node * @notice This contract holds all the L1-specific storage variables for the L1GNS contract, version 1 * @dev When adding new versions, make sure to move the gap to the new version and * reduce the size of the gap accordingly. */ abstract contract L1GNSV1Storage { - /// True for subgraph IDs that have been transferred to L2 + /// @notice True for subgraph IDs that have been transferred to L2 mapping(uint256 => bool) public subgraphTransferredToL2; /// @dev Storage gap to keep storage slots fixed in future versions uint256[50] private __gap; diff --git a/packages/contracts/contracts/discovery/ServiceRegistry.sol b/packages/contracts/contracts/discovery/ServiceRegistry.sol index 1eb1393d3..32db1fe1b 100644 --- a/packages/contracts/contracts/discovery/ServiceRegistry.sol +++ b/packages/contracts/contracts/discovery/ServiceRegistry.sol @@ -3,58 +3,68 @@ pragma solidity ^0.7.6; pragma abicoder v2; -import "../governance/Managed.sol"; -import "../upgrades/GraphUpgradeable.sol"; +import { Managed } from "../governance/Managed.sol"; +import { GraphUpgradeable } from "../upgrades/GraphUpgradeable.sol"; -import "./ServiceRegistryStorage.sol"; -import "./IServiceRegistry.sol"; +import { ServiceRegistryV1Storage } from "./ServiceRegistryStorage.sol"; +import { IServiceRegistry } from "@graphprotocol/interfaces/contracts/contracts/discovery/IServiceRegistry.sol"; /** * @title ServiceRegistry contract - * @dev This contract supports the service discovery process by allowing indexers to + * @author Edge & Node + * @notice This contract supports the service discovery process by allowing indexers to * register their service url and any other relevant information. */ contract ServiceRegistry is ServiceRegistryV1Storage, GraphUpgradeable, IServiceRegistry { // -- Events -- + /** + * @notice Emitted when an indexer registers their service + * @param indexer Address of the indexer + * @param url URL of the indexer service + * @param geohash Geohash of the indexer service location + */ event ServiceRegistered(address indexed indexer, string url, string geohash); + + /** + * @notice Emitted when an indexer unregisters their service + * @param indexer Address of the indexer + */ event ServiceUnregistered(address indexed indexer); /** - * @dev Check if the caller is authorized (indexer or operator) + * @notice Check if the caller is authorized (indexer or operator) + * @param _indexer Address of the indexer to check authorization for + * @return True if the caller is authorized, false otherwise */ function _isAuth(address _indexer) internal view returns (bool) { return msg.sender == _indexer || staking().isOperator(msg.sender, _indexer) == true; } /** - * @dev Initialize this contract. + * @notice Initialize this contract. + * @param _controller Address of the controller contract */ function initialize(address _controller) external onlyImpl { Managed._initialize(_controller); } /** - * @dev Register an indexer service - * @param _url URL of the indexer service - * @param _geohash Geohash of the indexer service location + * @inheritdoc IServiceRegistry */ function register(string calldata _url, string calldata _geohash) external override { _register(msg.sender, _url, _geohash); } /** - * @dev Register an indexer service - * @param _indexer Address of the indexer - * @param _url URL of the indexer service - * @param _geohash Geohash of the indexer service location + * @inheritdoc IServiceRegistry */ function registerFor(address _indexer, string calldata _url, string calldata _geohash) external override { _register(_indexer, _url, _geohash); } /** - * @dev Internal: Register an indexer service + * @notice Internal: Register an indexer service * @param _indexer Address of the indexer * @param _url URL of the indexer service * @param _geohash Geohash of the indexer service location @@ -69,22 +79,21 @@ contract ServiceRegistry is ServiceRegistryV1Storage, GraphUpgradeable, IService } /** - * @dev Unregister an indexer service + * @inheritdoc IServiceRegistry */ function unregister() external override { _unregister(msg.sender); } /** - * @dev Unregister an indexer service - * @param _indexer Address of the indexer + * @inheritdoc IServiceRegistry */ function unregisterFor(address _indexer) external override { _unregister(_indexer); } /** - * @dev Unregister an indexer service + * @notice Unregister an indexer service * @param _indexer Address of the indexer */ function _unregister(address _indexer) private { @@ -96,8 +105,7 @@ contract ServiceRegistry is ServiceRegistryV1Storage, GraphUpgradeable, IService } /** - * @dev Return the registration status of an indexer service - * @return True if the indexer service is registered + * @inheritdoc IServiceRegistry */ function isRegistered(address _indexer) public view override returns (bool) { return bytes(services[_indexer].url).length > 0; diff --git a/packages/contracts/contracts/discovery/ServiceRegistryStorage.sol b/packages/contracts/contracts/discovery/ServiceRegistryStorage.sol index 1cd484970..4ad8a7359 100644 --- a/packages/contracts/contracts/discovery/ServiceRegistryStorage.sol +++ b/packages/contracts/contracts/discovery/ServiceRegistryStorage.sol @@ -1,13 +1,22 @@ // SPDX-License-Identifier: GPL-2.0-or-later +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable named-parameters-mapping + pragma solidity ^0.7.6; -import "../governance/Managed.sol"; +import { Managed } from "../governance/Managed.sol"; -import "./IServiceRegistry.sol"; +import { IServiceRegistry } from "@graphprotocol/interfaces/contracts/contracts/discovery/IServiceRegistry.sol"; +/** + * @title Service Registry Storage V1 + * @author Edge & Node + * @notice Storage contract for the Service Registry + */ contract ServiceRegistryV1Storage is Managed { // -- State -- + /// @notice Mapping of indexer addresses to their service information mapping(address => IServiceRegistry.IndexerService) public services; } diff --git a/packages/contracts/contracts/discovery/SubgraphNFT.sol b/packages/contracts/contracts/discovery/SubgraphNFT.sol index 3c514718c..22fc307c0 100644 --- a/packages/contracts/contracts/discovery/SubgraphNFT.sol +++ b/packages/contracts/contracts/discovery/SubgraphNFT.sol @@ -2,35 +2,66 @@ pragma solidity ^0.7.6; -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; - -import "../governance/Governed.sol"; -import "../libraries/HexStrings.sol"; -import "./ISubgraphNFT.sol"; -import "./ISubgraphNFTDescriptor.sol"; - -/// @title NFT that represents ownership of a Subgraph +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-calldata-parameters, gas-indexed-events, gas-small-strings +// solhint-disable named-parameters-mapping + +import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import { Address } from "@openzeppelin/contracts/utils/Address.sol"; + +import { Governed } from "../governance/Governed.sol"; +import { HexStrings } from "../libraries/HexStrings.sol"; +import { ISubgraphNFT } from "@graphprotocol/interfaces/contracts/contracts/discovery/ISubgraphNFT.sol"; +import { ISubgraphNFTDescriptor } from "@graphprotocol/interfaces/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol"; + +/** + * @title NFT that represents ownership of a Subgraph + * @author Edge & Node + * @notice NFT that represents ownership of a Subgraph + */ contract SubgraphNFT is Governed, ERC721, ISubgraphNFT { // -- State -- + /// @notice Address of the minter contract address public minter; + /// @notice Address of the token descriptor contract ISubgraphNFTDescriptor public tokenDescriptor; + /// @dev Mapping from token ID to subgraph metadata hash mapping(uint256 => bytes32) private _subgraphMetadataHashes; // -- Events -- + /** + * @notice Emitted when the minter address is updated + * @param minter Address of the new minter + */ event MinterUpdated(address minter); + + /** + * @notice Emitted when the token descriptor is updated + * @param tokenDescriptor Address of the new token descriptor + */ event TokenDescriptorUpdated(address tokenDescriptor); + + /** + * @notice Emitted when subgraph metadata is updated + * @param tokenID ID of the token + * @param subgraphURI IPFS hash of the subgraph metadata + */ event SubgraphMetadataUpdated(uint256 indexed tokenID, bytes32 subgraphURI); // -- Modifiers -- + /// @dev Modifier to restrict access to minter only modifier onlyMinter() { require(msg.sender == minter, "Must be a minter"); _; } + /** + * @notice Constructor for the SubgraphNFT contract + * @param _governor Address that will have governance privileges + */ constructor(address _governor) ERC721("Subgraph", "SG") { _initialize(_governor); } @@ -38,9 +69,7 @@ contract SubgraphNFT is Governed, ERC721, ISubgraphNFT { // -- Config -- /** - * @notice Set the minter allowed to perform actions on the NFT. - * @dev Minter can mint, burn and update the metadata - * @param _minter Address of the allowed minter + * @inheritdoc ISubgraphNFT */ function setMinter(address _minter) external override onlyGovernor { _setMinter(_minter); @@ -57,16 +86,14 @@ contract SubgraphNFT is Governed, ERC721, ISubgraphNFT { } /** - * @notice Set the token descriptor contract. - * @dev Token descriptor can be zero. If set, it must be a contract. - * @param _tokenDescriptor Address of the contract that creates the NFT token URI + * @inheritdoc ISubgraphNFT */ function setTokenDescriptor(address _tokenDescriptor) external override onlyGovernor { _setTokenDescriptor(_tokenDescriptor); } /** - * @dev Internal: Set the token descriptor contract used to create the ERC-721 metadata URI. + * @notice Internal: Set the token descriptor contract used to create the ERC-721 metadata URI. * @param _tokenDescriptor Address of the contract that creates the NFT token URI */ function _setTokenDescriptor(address _tokenDescriptor) internal { @@ -79,9 +106,7 @@ contract SubgraphNFT is Governed, ERC721, ISubgraphNFT { } /** - * @notice Set the base URI. - * @dev Can be set to empty. - * @param _baseURI Base URI to use to build the token URI + * @inheritdoc ISubgraphNFT */ function setBaseURI(string memory _baseURI) external override onlyGovernor { _setBaseURI(_baseURI); @@ -90,29 +115,21 @@ contract SubgraphNFT is Governed, ERC721, ISubgraphNFT { // -- Minter actions -- /** - * @notice Mint `_tokenId` and transfers it to `_to`. - * @dev `tokenId` must not exist and `to` cannot be the zero address. - * @param _to Address receiving the minted NFT - * @param _tokenId ID of the NFT + * @inheritdoc ISubgraphNFT */ function mint(address _to, uint256 _tokenId) external override onlyMinter { _mint(_to, _tokenId); } /** - * @notice Burn `_tokenId`. - * @dev The approval is cleared when the token is burned. - * @param _tokenId ID of the NFT + * @inheritdoc ISubgraphNFT */ function burn(uint256 _tokenId) external override onlyMinter { _burn(_tokenId); } /** - * @notice Set the metadata for a subgraph represented by `_tokenId`. - * @dev `_tokenId` must exist. - * @param _tokenId ID of the NFT - * @param _subgraphMetadata IPFS hash for the metadata + * @inheritdoc ISubgraphNFT */ function setSubgraphMetadata(uint256 _tokenId, bytes32 _subgraphMetadata) external override onlyMinter { require(_exists(_tokenId), "ERC721Metadata: URI set of nonexistent token"); diff --git a/packages/contracts/contracts/discovery/SubgraphNFTDescriptor.sol b/packages/contracts/contracts/discovery/SubgraphNFTDescriptor.sol index 81f6da696..a4f5a5080 100644 --- a/packages/contracts/contracts/discovery/SubgraphNFTDescriptor.sol +++ b/packages/contracts/contracts/discovery/SubgraphNFTDescriptor.sol @@ -2,10 +2,14 @@ pragma solidity ^0.7.6; -import "../libraries/Base58Encoder.sol"; -import "./ISubgraphNFTDescriptor.sol"; +import { Base58Encoder } from "../libraries/Base58Encoder.sol"; +import { ISubgraphNFTDescriptor } from "@graphprotocol/interfaces/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol"; -/// @title Describes subgraph NFT tokens via URI +/** + * @title Describes subgraph NFT tokens via URI + * @author Edge & Node + * @notice Describes subgraph NFT tokens via URI + */ contract SubgraphNFTDescriptor is ISubgraphNFTDescriptor { /// @inheritdoc ISubgraphNFTDescriptor function tokenURI( diff --git a/packages/contracts/contracts/discovery/erc1056/EthereumDIDRegistry.sol b/packages/contracts/contracts/discovery/erc1056/EthereumDIDRegistry.sol index e8545dd4a..76c1a41f9 100644 --- a/packages/contracts/contracts/discovery/erc1056/EthereumDIDRegistry.sol +++ b/packages/contracts/contracts/discovery/erc1056/EthereumDIDRegistry.sol @@ -12,19 +12,51 @@ As well as all testnets pragma solidity ^0.7.6; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-increment-by-one, gas-indexed-events, gas-small-strings +// solhint-disable named-parameters-mapping + +/** + * @title Ethereum DID Registry + * @author Edge & Node + * @notice Registry for Ethereum Decentralized Identifiers (DIDs) + */ contract EthereumDIDRegistry { + /// @notice Mapping of identity addresses to their owners mapping(address => address) public owners; + /// @notice Mapping of identity addresses to delegate types to delegate addresses to validity periods mapping(address => mapping(bytes32 => mapping(address => uint256))) public delegates; + /// @notice Mapping of identity addresses to their last change block numbers mapping(address => uint256) public changed; + /// @notice Mapping of identity addresses to their nonce values mapping(address => uint256) public nonce; + /** + * @notice Modifier to restrict access to identity owners only + * @param identity The identity address + * @param actor The address performing the action + */ modifier onlyOwner(address identity, address actor) { require(actor == identityOwner(identity), "Caller must be the identity owner"); _; } + /** + * @notice Emitted when a DID owner is changed + * @param identity The identity address + * @param owner The new owner address + * @param previousChange Block number of the previous change + */ event DIDOwnerChanged(address indexed identity, address owner, uint256 previousChange); + /** + * @notice Emitted when a DID delegate is changed + * @param identity The identity address + * @param delegateType The type of delegate + * @param delegate The delegate address + * @param validTo Timestamp until which the delegate is valid + * @param previousChange Block number of the previous change + */ event DIDDelegateChanged( address indexed identity, bytes32 delegateType, @@ -33,6 +65,14 @@ contract EthereumDIDRegistry { uint256 previousChange ); + /** + * @notice Emitted when a DID attribute is changed + * @param identity The identity address + * @param name The attribute name + * @param value The attribute value + * @param validTo Timestamp until which the attribute is valid + * @param previousChange Block number of the previous change + */ event DIDAttributeChanged( address indexed identity, bytes32 name, @@ -41,6 +81,11 @@ contract EthereumDIDRegistry { uint256 previousChange ); + /** + * @notice Get the owner of an identity + * @param identity The identity address + * @return The address of the identity owner + */ function identityOwner(address identity) public view returns (address) { address owner = owners[identity]; if (owner != address(0)) { @@ -49,6 +94,15 @@ contract EthereumDIDRegistry { return identity; } + /** + * @notice Verify signature and return signer address + * @param identity The identity address + * @param sigV Recovery ID of the signature + * @param sigR R component of the signature + * @param sigS S component of the signature + * @param hash Hash that was signed + * @return The address of the signer + */ function checkSignature( address identity, uint8 sigV, @@ -62,22 +116,48 @@ contract EthereumDIDRegistry { return signer; } + /** + * @notice Check if a delegate is valid for an identity + * @param identity The identity address + * @param delegateType The type of delegate + * @param delegate The delegate address + * @return True if the delegate is valid, false otherwise + */ function validDelegate(address identity, bytes32 delegateType, address delegate) public view returns (bool) { uint256 validity = delegates[identity][keccak256(abi.encode(delegateType))][delegate]; /* solium-disable-next-line security/no-block-members*/ return (validity > block.timestamp); } + /** + * @notice Internal function to change the owner of an identity + * @param identity The identity address + * @param actor The address performing the action + * @param newOwner The new owner address + */ function changeOwner(address identity, address actor, address newOwner) internal onlyOwner(identity, actor) { owners[identity] = newOwner; emit DIDOwnerChanged(identity, newOwner, changed[identity]); changed[identity] = block.number; } + /** + * @notice Change the owner of an identity + * @param identity The identity address + * @param newOwner The new owner address + */ function changeOwner(address identity, address newOwner) public { changeOwner(identity, msg.sender, newOwner); } + /** + * @notice Change the owner of an identity using a signed message + * @param identity The identity address + * @param sigV Recovery ID of the signature + * @param sigR R component of the signature + * @param sigS S component of the signature + * @param newOwner The new owner address + */ function changeOwnerSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, address newOwner) public { bytes32 hash = keccak256( abi.encodePacked( @@ -93,6 +173,14 @@ contract EthereumDIDRegistry { changeOwner(identity, checkSignature(identity, sigV, sigR, sigS, hash), newOwner); } + /** + * @notice Internal function to add a delegate for an identity + * @param identity The identity address + * @param actor The address performing the action + * @param delegateType The type of delegate + * @param delegate The delegate address + * @param validity The validity period in seconds + */ function addDelegate( address identity, address actor, @@ -113,10 +201,27 @@ contract EthereumDIDRegistry { changed[identity] = block.number; } + /** + * @notice Add a delegate for an identity + * @param identity The identity to add a delegate for + * @param delegateType The type of delegate + * @param delegate The address of the delegate + * @param validity The validity period in seconds + */ function addDelegate(address identity, bytes32 delegateType, address delegate, uint256 validity) public { addDelegate(identity, msg.sender, delegateType, delegate, validity); } + /** + * @notice Add a delegate for an identity using a signed message + * @param identity The identity to add a delegate for + * @param sigV The recovery id of the signature + * @param sigR The r component of the signature + * @param sigS The s component of the signature + * @param delegateType The type of delegate + * @param delegate The address of the delegate + * @param validity The validity period in seconds + */ function addDelegateSigned( address identity, uint8 sigV, @@ -142,6 +247,13 @@ contract EthereumDIDRegistry { addDelegate(identity, checkSignature(identity, sigV, sigR, sigS, hash), delegateType, delegate, validity); } + /** + * @notice Internal function to revoke a delegate for an identity + * @param identity The identity address + * @param actor The address performing the action + * @param delegateType The type of delegate + * @param delegate The delegate address + */ function revokeDelegate( address identity, address actor, @@ -155,10 +267,25 @@ contract EthereumDIDRegistry { changed[identity] = block.number; } + /** + * @notice Revoke a delegate for an identity + * @param identity The identity to revoke a delegate for + * @param delegateType The type of delegate + * @param delegate The address of the delegate + */ function revokeDelegate(address identity, bytes32 delegateType, address delegate) public { revokeDelegate(identity, msg.sender, delegateType, delegate); } + /** + * @notice Revoke a delegate for an identity using a signed message + * @param identity The identity to revoke a delegate for + * @param sigV The recovery id of the signature + * @param sigR The r component of the signature + * @param sigS The s component of the signature + * @param delegateType The type of delegate + * @param delegate The address of the delegate + */ function revokeDelegateSigned( address identity, uint8 sigV, @@ -182,6 +309,14 @@ contract EthereumDIDRegistry { revokeDelegate(identity, checkSignature(identity, sigV, sigR, sigS, hash), delegateType, delegate); } + /** + * @notice Internal function to set an attribute for an identity + * @param identity The identity address + * @param actor The address performing the action + * @param name The attribute name + * @param value The attribute value + * @param validity The validity period in seconds + */ function setAttribute( address identity, address actor, @@ -194,10 +329,27 @@ contract EthereumDIDRegistry { changed[identity] = block.number; } + /** + * @notice Set an attribute for an identity + * @param identity The identity to set an attribute for + * @param name The name of the attribute + * @param value The value of the attribute + * @param validity The validity period in seconds + */ function setAttribute(address identity, bytes32 name, bytes memory value, uint256 validity) public { setAttribute(identity, msg.sender, name, value, validity); } + /** + * @notice Set an attribute for an identity using a signed message + * @param identity The identity to set an attribute for + * @param sigV The recovery id of the signature + * @param sigR The r component of the signature + * @param sigS The s component of the signature + * @param name The name of the attribute + * @param value The value of the attribute + * @param validity The validity period in seconds + */ function setAttributeSigned( address identity, uint8 sigV, @@ -223,6 +375,13 @@ contract EthereumDIDRegistry { setAttribute(identity, checkSignature(identity, sigV, sigR, sigS, hash), name, value, validity); } + /** + * @notice Internal function to revoke an attribute for an identity + * @param identity The identity address + * @param actor The address performing the action + * @param name The attribute name + * @param value The attribute value + */ function revokeAttribute( address identity, address actor, @@ -233,10 +392,25 @@ contract EthereumDIDRegistry { changed[identity] = block.number; } + /** + * @notice Revoke an attribute for an identity + * @param identity The identity to revoke an attribute for + * @param name The name of the attribute + * @param value The value of the attribute + */ function revokeAttribute(address identity, bytes32 name, bytes memory value) public { revokeAttribute(identity, msg.sender, name, value); } + /** + * @notice Revoke an attribute for an identity using a signed message + * @param identity The identity to revoke an attribute for + * @param sigV The recovery id of the signature + * @param sigR The r component of the signature + * @param sigS The s component of the signature + * @param name The name of the attribute + * @param value The value of the attribute + */ function revokeAttributeSigned( address identity, uint8 sigV, diff --git a/packages/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol b/packages/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol deleted file mode 100644 index 8de69f304..000000000 --- a/packages/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -pragma solidity ^0.7.6; - -interface IEthereumDIDRegistry { - function identityOwner(address identity) external view returns (address); - - function setAttribute(address identity, bytes32 name, bytes calldata value, uint256 validity) external; -} diff --git a/packages/contracts/contracts/disputes/DisputeManager.sol b/packages/contracts/contracts/disputes/DisputeManager.sol index 013a21b03..9ef426453 100644 --- a/packages/contracts/contracts/disputes/DisputeManager.sol +++ b/packages/contracts/contracts/disputes/DisputeManager.sol @@ -3,18 +3,23 @@ pragma solidity ^0.7.6; pragma abicoder v2; -import "@openzeppelin/contracts/math/SafeMath.sol"; -import "@openzeppelin/contracts/cryptography/ECDSA.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-small-strings, gas-strict-inequalities -import "../governance/Managed.sol"; -import "../upgrades/GraphUpgradeable.sol"; -import "../utils/TokenUtils.sol"; +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; +import { ECDSA } from "@openzeppelin/contracts/cryptography/ECDSA.sol"; -import "./DisputeManagerStorage.sol"; -import "./IDisputeManager.sol"; +import { Managed } from "../governance/Managed.sol"; +import { GraphUpgradeable } from "../upgrades/GraphUpgradeable.sol"; +import { TokenUtils } from "../utils/TokenUtils.sol"; +import { IStaking } from "@graphprotocol/interfaces/contracts/contracts/staking/IStaking.sol"; -/* +import { DisputeManagerV1Storage } from "./DisputeManagerStorage.sol"; +import { IDisputeManager } from "@graphprotocol/interfaces/contracts/contracts/disputes/IDisputeManager.sol"; + +/** * @title DisputeManager + * @author Edge & Node * @notice Provides a way to align the incentives of participants by having slashing as deterrent * for incorrect behaviour. * @@ -41,39 +46,61 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa // -- EIP-712 -- + /// @dev EIP-712 domain type hash for signature verification bytes32 private constant DOMAIN_TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)"); + /// @dev EIP-712 domain name hash bytes32 private constant DOMAIN_NAME_HASH = keccak256("Graph Protocol"); + /// @dev EIP-712 domain version hash bytes32 private constant DOMAIN_VERSION_HASH = keccak256("0"); + /// @dev EIP-712 domain salt for uniqueness bytes32 private constant DOMAIN_SALT = 0xa070ffb1cd7409649bf77822cce74495468e06dbfaef09556838bf188679b9c2; + /// @dev EIP-712 receipt type hash for attestation verification bytes32 private constant RECEIPT_TYPE_HASH = keccak256("Receipt(bytes32 requestCID,bytes32 responseCID,bytes32 subgraphDeploymentID)"); // -- Constants -- - // Attestation size is the sum of the receipt (96) + signature (65) + /// @dev Total size of attestation in bytes (receipt + signature) uint256 private constant ATTESTATION_SIZE_BYTES = RECEIPT_SIZE_BYTES + SIG_SIZE_BYTES; + /// @dev Size of receipt in bytes uint256 private constant RECEIPT_SIZE_BYTES = 96; + /// @dev Length of signature R component in bytes uint256 private constant SIG_R_LENGTH = 32; + /// @dev Length of signature S component in bytes uint256 private constant SIG_S_LENGTH = 32; + /// @dev Length of signature V component in bytes uint256 private constant SIG_V_LENGTH = 1; + /// @dev Offset of signature R component in attestation data uint256 private constant SIG_R_OFFSET = RECEIPT_SIZE_BYTES; + /// @dev Offset of signature S component in attestation data uint256 private constant SIG_S_OFFSET = RECEIPT_SIZE_BYTES + SIG_R_LENGTH; + /// @dev Offset of signature V component in attestation data uint256 private constant SIG_V_OFFSET = RECEIPT_SIZE_BYTES + SIG_R_LENGTH + SIG_S_LENGTH; + /// @dev Total size of signature in bytes uint256 private constant SIG_SIZE_BYTES = SIG_R_LENGTH + SIG_S_LENGTH + SIG_V_LENGTH; + /// @dev Length of uint8 type in bytes uint256 private constant UINT8_BYTE_LENGTH = 1; + /// @dev Length of bytes32 type in bytes uint256 private constant BYTES32_BYTE_LENGTH = 32; + /// @dev Maximum percentage in parts per million (100%) uint256 private constant MAX_PPM = 1000000; // 100% in parts per million // -- Events -- /** - * @dev Emitted when a query dispute is created for `subgraphDeploymentID` and `indexer` + * @notice Emitted when a query dispute is created for `subgraphDeploymentID` and `indexer` * by `fisherman`. * The event emits the amount of `tokens` deposited by the fisherman and `attestation` submitted. + * @param disputeID ID of the dispute + * @param indexer Address of the indexer being disputed + * @param fisherman Address of the fisherman creating the dispute + * @param tokens Amount of tokens deposited by the fisherman + * @param subgraphDeploymentID Subgraph deployment ID being disputed + * @param attestation Attestation data submitted */ event QueryDisputeCreated( bytes32 indexed disputeID, @@ -85,9 +112,14 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa ); /** - * @dev Emitted when an indexing dispute is created for `allocationID` and `indexer` + * @notice Emitted when an indexing dispute is created for `allocationID` and `indexer` * by `fisherman`. * The event emits the amount of `tokens` deposited by the fisherman. + * @param disputeID ID of the dispute + * @param indexer Address of the indexer being disputed + * @param fisherman Address of the fisherman creating the dispute + * @param tokens Amount of tokens deposited by the fisherman + * @param allocationID Allocation ID being disputed */ event IndexingDisputeCreated( bytes32 indexed disputeID, @@ -98,8 +130,12 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa ); /** - * @dev Emitted when arbitrator accepts a `disputeID` to `indexer` created by `fisherman`. + * @notice Emitted when arbitrator accepts a `disputeID` to `indexer` created by `fisherman`. * The event emits the amount `tokens` transferred to the fisherman, the deposit plus reward. + * @param disputeID ID of the dispute + * @param indexer Address of the indexer being disputed + * @param fisherman Address of the fisherman who created the dispute + * @param tokens Amount of tokens transferred to the fisherman (deposit plus reward) */ event DisputeAccepted( bytes32 indexed disputeID, @@ -109,8 +145,12 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa ); /** - * @dev Emitted when arbitrator rejects a `disputeID` for `indexer` created by `fisherman`. + * @notice Emitted when arbitrator rejects a `disputeID` for `indexer` created by `fisherman`. * The event emits the amount `tokens` burned from the fisherman deposit. + * @param disputeID ID of the dispute + * @param indexer Address of the indexer being disputed + * @param fisherman Address of the fisherman who created the dispute + * @param tokens Amount of tokens burned from the fisherman deposit */ event DisputeRejected( bytes32 indexed disputeID, @@ -120,20 +160,29 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa ); /** - * @dev Emitted when arbitrator draw a `disputeID` for `indexer` created by `fisherman`. + * @notice Emitted when arbitrator draw a `disputeID` for `indexer` created by `fisherman`. * The event emits the amount `tokens` used as deposit and returned to the fisherman. + * @param disputeID ID of the dispute + * @param indexer Address of the indexer being disputed + * @param fisherman Address of the fisherman who created the dispute + * @param tokens Amount of tokens used as deposit and returned to the fisherman */ event DisputeDrawn(bytes32 indexed disputeID, address indexed indexer, address indexed fisherman, uint256 tokens); /** - * @dev Emitted when two disputes are in conflict to link them. + * @notice Emitted when two disputes are in conflict to link them. * This event will be emitted after each DisputeCreated event is emitted * for each of the individual disputes. + * @param disputeID1 ID of the first dispute + * @param disputeID2 ID of the second dispute */ event DisputeLinked(bytes32 indexed disputeID1, bytes32 indexed disputeID2); // -- Modifiers -- + /** + * @notice Internal function to check if the caller is the arbitrator + */ function _onlyArbitrator() internal view { require(msg.sender == arbitrator, "Caller is not the Arbitrator"); } @@ -146,6 +195,10 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa _; } + /** + * @dev Check if the dispute exists and is pending + * @param _disputeID ID of the dispute to check + */ modifier onlyPendingDispute(bytes32 _disputeID) { require(isDisputeCreated(_disputeID), "Dispute does not exist"); require(disputes[_disputeID].status == IDisputeManager.DisputeStatus.Pending, "Dispute must be pending"); @@ -155,7 +208,8 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa // -- Functions -- /** - * @dev Initialize this contract. + * @notice Initialize this contract. + * @param _controller Controller address * @param _arbitrator Arbitrator role * @param _minimumDeposit Minimum deposit required to create a Dispute * @param _fishermanRewardPercentage Percent of slashed funds for fisherman (ppm) @@ -192,16 +246,13 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Set the arbitrator address. - * @notice Update the arbitrator to `_arbitrator` - * @param _arbitrator The address of the arbitration contract or party + * @inheritdoc IDisputeManager */ function setArbitrator(address _arbitrator) external override onlyGovernor { _setArbitrator(_arbitrator); } /** - * @dev Internal: Set the arbitrator address. * @notice Update the arbitrator to `_arbitrator` * @param _arbitrator The address of the arbitration contract or party */ @@ -212,16 +263,13 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Set the minimum deposit required to create a dispute. - * @notice Update the minimum deposit to `_minimumDeposit` Graph Tokens - * @param _minimumDeposit The minimum deposit in Graph Tokens + * @inheritdoc IDisputeManager */ function setMinimumDeposit(uint256 _minimumDeposit) external override onlyGovernor { _setMinimumDeposit(_minimumDeposit); } /** - * @dev Internal: Set the minimum deposit required to create a dispute. * @notice Update the minimum deposit to `_minimumDeposit` Graph Tokens * @param _minimumDeposit The minimum deposit in Graph Tokens */ @@ -232,17 +280,14 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Set the percent reward that the fisherman gets when slashing occurs. - * @notice Update the reward percentage to `_percentage` - * @param _percentage Reward as a percentage of indexer stake + * @inheritdoc IDisputeManager */ function setFishermanRewardPercentage(uint32 _percentage) external override onlyGovernor { _setFishermanRewardPercentage(_percentage); } /** - * @dev Internal: Set the percent reward that the fisherman gets when slashing occurs. - * @notice Update the reward percentage to `_percentage` + * @notice Set the percent reward that the fisherman gets when slashing occurs. * @param _percentage Reward as a percentage of indexer stake */ function _setFishermanRewardPercentage(uint32 _percentage) private { @@ -253,16 +298,14 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Set the percentage used for slashing indexers. - * @param _qryPercentage Percentage slashing for query disputes - * @param _idxPercentage Percentage slashing for indexing disputes + * @inheritdoc IDisputeManager */ function setSlashingPercentage(uint32 _qryPercentage, uint32 _idxPercentage) external override onlyGovernor { _setSlashingPercentage(_qryPercentage, _idxPercentage); } /** - * @dev Internal: Set the percentage used for slashing indexers. + * @notice Internal: Set the percentage used for slashing indexers. * @param _qryPercentage Percentage slashing for query disputes * @param _idxPercentage Percentage slashing for indexing disputes */ @@ -279,21 +322,16 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Return whether a dispute exists or not. - * @notice Return if dispute with ID `_disputeID` exists - * @param _disputeID True if dispute already exists + * @inheritdoc IDisputeManager */ function isDisputeCreated(bytes32 _disputeID) public view override returns (bool) { return disputes[_disputeID].status != DisputeStatus.Null; } /** - * @dev Get the message hash that an indexer used to sign the receipt. - * Encodes a receipt using a domain separator, as described on + * @inheritdoc IDisputeManager + * @dev Encodes a receipt using a domain separator, as described on * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#specification. - * @notice Return the message hash used to sign the receipt - * @param _receipt Receipt returned by indexer and submitted by fisherman - * @return Message hash used to sign the receipt */ function encodeHashReceipt(Receipt memory _receipt) public view override returns (bytes32) { return @@ -314,11 +352,8 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Returns if two attestations are conflicting. - * Everything must match except for the responseID. - * @param _attestation1 Attestation - * @param _attestation2 Attestation - * @return True if the two attestations are conflicting + * @inheritdoc IDisputeManager + * @dev Everything must match except for the responseID. */ function areConflictingAttestations( Attestation memory _attestation1, @@ -330,9 +365,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Returns the indexer that signed an attestation. - * @param _attestation Attestation - * @return Indexer address + * @inheritdoc IDisputeManager */ function getAttestationIndexer(Attestation memory _attestation) public view override returns (address) { // Get attestation signer. Indexers signs with the allocationID @@ -348,11 +381,9 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Create a query dispute for the arbitrator to resolve. - * This function is called by a fisherman that will need to `_deposit` at + * @inheritdoc IDisputeManager + * @dev This function is called by a fisherman that will need to `_deposit` at * least `minimumDeposit` GRT tokens. - * @param _attestationData Attestation bytes submitted by the fisherman - * @param _deposit Amount of tokens staked as deposit */ function createQueryDispute(bytes calldata _attestationData, uint256 _deposit) external override returns (bytes32) { // Get funds from submitter @@ -369,16 +400,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Create query disputes for two conflicting attestations. - * A conflicting attestation is a proof presented by two different indexers - * where for the same request on a subgraph the response is different. - * For this type of dispute the submitter is not required to present a deposit - * as one of the attestation is considered to be right. - * Two linked disputes will be created and if the arbitrator resolve one, the other - * one will be automatically resolved. - * @param _attestationData1 First attestation data submitted - * @param _attestationData2 Second attestation data submitted - * @return DisputeID1, DisputeID2 + * @inheritdoc IDisputeManager */ function createQueryDisputeConflict( bytes calldata _attestationData1, @@ -409,7 +431,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Create a query dispute passing the parsed attestation. + * @notice Create a query dispute passing the parsed attestation. * To be used in createQueryDispute() and createQueryDisputeConflict() * to avoid calling parseAttestation() multiple times * `_attestationData` is only passed to be emitted @@ -472,8 +494,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * The disputes are created in reference to an allocationID * This function is called by a challenger that will need to `_deposit` at * least `minimumDeposit` GRT tokens. - * @param _allocationID The allocation to dispute - * @param _deposit Amount of tokens staked as deposit + * @inheritdoc IDisputeManager */ function createIndexingDispute(address _allocationID, uint256 _deposit) external override returns (bytes32) { // Get funds from submitter @@ -484,12 +505,12 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Create indexing dispute internal function. + * @notice Create indexing dispute internal function. * @param _fisherman The challenger creating the dispute * @param _deposit Amount of tokens staked as deposit * @param _allocationID Allocation disputed + * @return disputeID The ID of the created dispute */ - function _createIndexingDisputeWithAllocation( address _fisherman, uint256 _deposit, @@ -525,12 +546,10 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev The arbitrator accepts a dispute as being valid. - * This function will revert if the indexer is not slashable, whether because it does not have + * @dev This function will revert if the indexer is not slashable, whether because it does not have * any stake available or the slashing percentage is configured to be zero. In those cases * a dispute must be resolved using drawDispute or rejectDispute. - * @notice Accept a dispute with ID `_disputeID` - * @param _disputeID ID of the dispute to be accepted + * @inheritdoc IDisputeManager */ function acceptDispute(bytes32 _disputeID) external override onlyArbitrator onlyPendingDispute(_disputeID) { Dispute storage dispute = disputes[_disputeID]; @@ -552,9 +571,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev The arbitrator rejects a dispute as being invalid. - * @notice Reject a dispute with ID `_disputeID` - * @param _disputeID ID of the dispute to be rejected + * @inheritdoc IDisputeManager */ function rejectDispute(bytes32 _disputeID) public override onlyArbitrator onlyPendingDispute(_disputeID) { Dispute storage dispute = disputes[_disputeID]; @@ -575,9 +592,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev The arbitrator draws dispute. - * @notice Ignore a dispute with ID `_disputeID` - * @param _disputeID ID of the dispute to be disregarded + * @inheritdoc IDisputeManager */ function drawDispute(bytes32 _disputeID) external override onlyArbitrator onlyPendingDispute(_disputeID) { Dispute storage dispute = disputes[_disputeID]; @@ -595,7 +610,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Returns whether the dispute is for a conflicting attestation or not. + * @notice Returns whether the dispute is for a conflicting attestation or not. * @param _dispute Dispute * @return True conflicting attestation dispute */ @@ -606,7 +621,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Resolve the conflicting dispute if there is any for the one passed to this function. + * @notice Resolve the conflicting dispute if there is any for the one passed to this function. * @param _dispute Dispute * @return True if resolved */ @@ -621,7 +636,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Pull deposit from submitter account. + * @notice Pull deposit from submitter account. * @param _deposit Amount of tokens to deposit */ function _pullSubmitterDeposit(uint256 _deposit) private { @@ -633,7 +648,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Make the staking contract slash the indexer and reward the challenger. + * @notice Make the staking contract slash the indexer and reward the challenger. * Give the challenger a reward equal to the fishermanRewardPercentage of slashed amount * @param _indexer Address of the indexer * @param _challenger Address of the challenger @@ -664,7 +679,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Return the slashing percentage for the dispute type. + * @notice Return the slashing percentage for the dispute type. * @param _disputeType Dispute type * @return Slashing percentage to use for the dispute type */ @@ -675,7 +690,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Recover the signer address of the `_attestation`. + * @notice Recover the signer address of the `_attestation`. * @param _attestation The attestation struct * @return Signer address */ @@ -694,11 +709,12 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Get the running network chain ID + * @notice Get the running network chain ID * @return The chain ID */ function _getChainID() private pure returns (uint256) { uint256 id; + // solhint-disable-next-line no-inline-assembly assembly { id := chainid() } @@ -706,7 +722,8 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Parse the bytes attestation into a struct from `_data`. + * @notice Parse the bytes attestation into a struct from `_data`. + * @param _data The bytes data to parse into an attestation * @return Attestation struct */ function _parseAttestation(bytes memory _data) private pure returns (Attestation memory) { @@ -729,13 +746,16 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Parse a uint8 from `_bytes` starting at offset `_start`. + * @notice Parse a uint8 from `_bytes` starting at offset `_start`. + * @param _bytes The bytes array to parse from + * @param _start The starting offset in the bytes array * @return uint8 value */ function _toUint8(bytes memory _bytes, uint256 _start) private pure returns (uint8) { require(_bytes.length >= (_start + UINT8_BYTE_LENGTH), "Bytes: out of bounds"); uint8 tempUint; + // solhint-disable-next-line no-inline-assembly assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } @@ -744,13 +764,16 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Parse a bytes32 from `_bytes` starting at offset `_start`. + * @notice Parse a bytes32 from `_bytes` starting at offset `_start`. + * @param _bytes The bytes array to parse from + * @param _start The starting offset in the bytes array * @return bytes32 value */ function _toBytes32(bytes memory _bytes, uint256 _start) private pure returns (bytes32) { require(_bytes.length >= (_start + BYTES32_BYTE_LENGTH), "Bytes: out of bounds"); bytes32 tempBytes32; + // solhint-disable-next-line no-inline-assembly assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } diff --git a/packages/contracts/contracts/disputes/DisputeManagerStorage.sol b/packages/contracts/contracts/disputes/DisputeManagerStorage.sol index 4df6e0ae6..f2ad2b7c3 100644 --- a/packages/contracts/contracts/disputes/DisputeManagerStorage.sol +++ b/packages/contracts/contracts/disputes/DisputeManagerStorage.sol @@ -1,34 +1,44 @@ // SPDX-License-Identifier: GPL-2.0-or-later +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable named-parameters-mapping + pragma solidity ^0.7.6; -import "../governance/Managed.sol"; +import { Managed } from "../governance/Managed.sol"; -import "./IDisputeManager.sol"; +import { IDisputeManager } from "@graphprotocol/interfaces/contracts/contracts/disputes/IDisputeManager.sol"; +/** + * @title Dispute Manager Storage V1 + * @author Edge & Node + * @notice Storage contract for the Dispute Manager + */ contract DisputeManagerV1Storage is Managed { // -- State -- - bytes32 internal DOMAIN_SEPARATOR; + /// @dev Domain separator for EIP-712 signature verification + bytes32 internal DOMAIN_SEPARATOR; // solhint-disable-line var-name-mixedcase - // The arbitrator is solely in control of arbitrating disputes + /// @notice The arbitrator is solely in control of arbitrating disputes address public arbitrator; - // Minimum deposit required to create a Dispute + /// @notice Minimum deposit required to create a Dispute uint256 public minimumDeposit; // -- Slot 0xf - // Percentage of indexer slashed funds to assign as a reward to fisherman in successful dispute - // Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%) + /// @notice Percentage of indexer slashed funds to assign as a reward to fisherman in successful dispute + /// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%) uint32 public fishermanRewardPercentage; - // Percentage of indexer stake to slash on disputes - // Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%) + /// @notice Percentage of indexer stake to slash on disputes + /// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%) uint32 public qrySlashingPercentage; + /// @notice Percentage of indexer stake to slash on disputes uint32 public idxSlashingPercentage; // -- Slot 0x10 - // Disputes created : disputeID => Dispute - // disputeID - check creation functions to see how disputeID is built + /// @notice Disputes created : disputeID => Dispute + /// @dev disputeID - check creation functions to see how disputeID is built mapping(bytes32 => IDisputeManager.Dispute) public disputes; } diff --git a/packages/contracts/contracts/disputes/IDisputeManager.sol b/packages/contracts/contracts/disputes/IDisputeManager.sol deleted file mode 100644 index e42386941..000000000 --- a/packages/contracts/contracts/disputes/IDisputeManager.sol +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity >=0.6.12 <0.8.0 || 0.8.27; -pragma abicoder v2; - -interface IDisputeManager { - // -- Dispute -- - - enum DisputeType { - Null, - IndexingDispute, - QueryDispute - } - - enum DisputeStatus { - Null, - Accepted, - Rejected, - Drawn, - Pending - } - - // Disputes contain info necessary for the Arbitrator to verify and resolve - struct Dispute { - address indexer; - address fisherman; - uint256 deposit; - bytes32 relatedDisputeID; - DisputeType disputeType; - DisputeStatus status; - } - - // -- Attestation -- - - // Receipt content sent from indexer in response to request - struct Receipt { - bytes32 requestCID; - bytes32 responseCID; - bytes32 subgraphDeploymentID; - } - - // Attestation sent from indexer in response to a request - struct Attestation { - bytes32 requestCID; - bytes32 responseCID; - bytes32 subgraphDeploymentID; - bytes32 r; - bytes32 s; - uint8 v; - } - - // -- Configuration -- - - function setArbitrator(address _arbitrator) external; - - function setMinimumDeposit(uint256 _minimumDeposit) external; - - function setFishermanRewardPercentage(uint32 _percentage) external; - - function setSlashingPercentage(uint32 _qryPercentage, uint32 _idxPercentage) external; - - // -- Getters -- - - function isDisputeCreated(bytes32 _disputeID) external view returns (bool); - - function encodeHashReceipt(Receipt memory _receipt) external view returns (bytes32); - - function areConflictingAttestations( - Attestation memory _attestation1, - Attestation memory _attestation2 - ) external pure returns (bool); - - function getAttestationIndexer(Attestation memory _attestation) external view returns (address); - - // -- Dispute -- - - function createQueryDispute(bytes calldata _attestationData, uint256 _deposit) external returns (bytes32); - - function createQueryDisputeConflict( - bytes calldata _attestationData1, - bytes calldata _attestationData2 - ) external returns (bytes32, bytes32); - - function createIndexingDispute(address _allocationID, uint256 _deposit) external returns (bytes32); - - function acceptDispute(bytes32 _disputeID) external; - - function rejectDispute(bytes32 _disputeID) external; - - function drawDispute(bytes32 _disputeID) external; -} diff --git a/packages/contracts/contracts/epochs/EpochManager.sol b/packages/contracts/contracts/epochs/EpochManager.sol index 281b63896..d69002794 100644 --- a/packages/contracts/contracts/epochs/EpochManager.sol +++ b/packages/contracts/contracts/epochs/EpochManager.sol @@ -2,27 +2,45 @@ pragma solidity ^0.7.6; -import "@openzeppelin/contracts/math/SafeMath.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events, gas-small-strings, gas-strict-inequalities -import "../upgrades/GraphUpgradeable.sol"; +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; -import "./EpochManagerStorage.sol"; -import "./IEpochManager.sol"; +import { GraphUpgradeable } from "../upgrades/GraphUpgradeable.sol"; +import { Managed } from "../governance/Managed.sol"; + +import { EpochManagerV1Storage } from "./EpochManagerStorage.sol"; +import { IEpochManager } from "@graphprotocol/interfaces/contracts/contracts/epochs/IEpochManager.sol"; /** * @title EpochManager contract - * @dev Produce epochs based on a number of blocks to coordinate contracts in the protocol. + * @author Edge & Node + * @notice Produce epochs based on a number of blocks to coordinate contracts in the protocol. */ contract EpochManager is EpochManagerV1Storage, GraphUpgradeable, IEpochManager { using SafeMath for uint256; // -- Events -- + /** + * @notice Emitted when an epoch is run + * @param epoch The epoch number that was run + * @param caller Address that called runEpoch() + */ event EpochRun(uint256 indexed epoch, address caller); + + /** + * @notice Emitted when the epoch length is updated + * @param epoch The epoch when the length was updated + * @param epochLength The new epoch length in blocks + */ event EpochLengthUpdate(uint256 indexed epoch, uint256 epochLength); /** - * @dev Initialize this contract. + * @notice Initialize this contract. + * @param _controller Address of the Controller contract + * @param _epochLength Length of each epoch in blocks */ function initialize(address _controller, uint256 _epochLength) external onlyImpl { require(_epochLength > 0, "Epoch length cannot be 0"); @@ -39,9 +57,7 @@ contract EpochManager is EpochManagerV1Storage, GraphUpgradeable, IEpochManager } /** - * @dev Set the epoch length. - * @notice Set epoch length to `_epochLength` blocks - * @param _epochLength Epoch length in blocks + * @inheritdoc IEpochManager */ function setEpochLength(uint256 _epochLength) external override onlyGovernor { require(_epochLength > 0, "Epoch length cannot be 0"); @@ -55,8 +71,7 @@ contract EpochManager is EpochManagerV1Storage, GraphUpgradeable, IEpochManager } /** - * @dev Run a new epoch, should be called once at the start of any epoch. - * @notice Perform state changes for the current epoch + * @inheritdoc IEpochManager */ function runEpoch() external override { // Check if already called for the current epoch @@ -70,24 +85,21 @@ contract EpochManager is EpochManagerV1Storage, GraphUpgradeable, IEpochManager } /** - * @dev Return true if the current epoch has already run. - * @return Return true if current epoch is the last epoch that has run + * @inheritdoc IEpochManager */ function isCurrentEpochRun() public view override returns (bool) { return lastRunEpoch == currentEpoch(); } /** - * @dev Return current block number. - * @return Block number + * @inheritdoc IEpochManager */ function blockNum() public view override returns (uint256) { return block.number; } /** - * @dev Return blockhash for a block. - * @return BlockHash for `_block` number + * @inheritdoc IEpochManager */ function blockHash(uint256 _block) external view override returns (bytes32) { uint256 currentBlock = blockNum(); @@ -99,33 +111,28 @@ contract EpochManager is EpochManagerV1Storage, GraphUpgradeable, IEpochManager } /** - * @dev Return the current epoch, it may have not been run yet. - * @return The current epoch based on epoch length + * @inheritdoc IEpochManager */ function currentEpoch() public view override returns (uint256) { return lastLengthUpdateEpoch.add(epochsSinceUpdate()); } /** - * @dev Return block where the current epoch started. - * @return The block number when the current epoch started + * @inheritdoc IEpochManager */ function currentEpochBlock() public view override returns (uint256) { return lastLengthUpdateBlock.add(epochsSinceUpdate().mul(epochLength)); } /** - * @dev Return the number of blocks that passed since current epoch started. - * @return Blocks that passed since start of epoch + * @inheritdoc IEpochManager */ function currentEpochBlockSinceStart() external view override returns (uint256) { return blockNum() - currentEpochBlock(); } /** - * @dev Return the number of epoch that passed since another epoch. - * @param _epoch Epoch to use as since epoch value - * @return Number of epochs and current epoch + * @inheritdoc IEpochManager */ function epochsSince(uint256 _epoch) external view override returns (uint256) { uint256 epoch = currentEpoch(); @@ -133,8 +140,7 @@ contract EpochManager is EpochManagerV1Storage, GraphUpgradeable, IEpochManager } /** - * @dev Return number of epochs passed since last epoch length update. - * @return The number of epoch that passed since last epoch length update + * @inheritdoc IEpochManager */ function epochsSinceUpdate() public view override returns (uint256) { return blockNum().sub(lastLengthUpdateBlock).div(epochLength); diff --git a/packages/contracts/contracts/epochs/EpochManagerStorage.sol b/packages/contracts/contracts/epochs/EpochManagerStorage.sol index 5f8599434..894f34a46 100644 --- a/packages/contracts/contracts/epochs/EpochManagerStorage.sol +++ b/packages/contracts/contracts/epochs/EpochManagerStorage.sol @@ -2,18 +2,24 @@ pragma solidity ^0.7.6; -import "../governance/Managed.sol"; +import { Managed } from "../governance/Managed.sol"; +/** + * @title Epoch Manager Storage V1 + * @author Edge & Node + * @notice Storage contract for the Epoch Manager + */ contract EpochManagerV1Storage is Managed { // -- State -- - // Epoch length in blocks + /// @notice Epoch length in blocks uint256 public epochLength; - // Epoch that was last run + /// @notice Epoch that was last run uint256 public lastRunEpoch; - // Block and epoch when epoch length was last updated + /// @notice Epoch when epoch length was last updated uint256 public lastLengthUpdateEpoch; + /// @notice Block when epoch length was last updated uint256 public lastLengthUpdateBlock; } diff --git a/packages/contracts/contracts/epochs/IEpochManager.sol b/packages/contracts/contracts/epochs/IEpochManager.sol deleted file mode 100644 index c65280d59..000000000 --- a/packages/contracts/contracts/epochs/IEpochManager.sol +++ /dev/null @@ -1,31 +0,0 @@ -// 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); -} diff --git a/packages/contracts/contracts/gateway/BridgeEscrow.sol b/packages/contracts/contracts/gateway/BridgeEscrow.sol index 73bc0a3d7..d3b50edc8 100644 --- a/packages/contracts/contracts/gateway/BridgeEscrow.sol +++ b/packages/contracts/contracts/gateway/BridgeEscrow.sol @@ -9,7 +9,8 @@ import { Managed } from "../governance/Managed.sol"; /** * @title Bridge Escrow - * @dev This contracts acts as a gateway for an L2 bridge (or several). It simply holds GRT and has + * @author Edge & Node + * @notice This contracts acts as a gateway for an L2 bridge (or several). It simply holds GRT and has * a set of spenders that can transfer the tokens; the L1 side of each L2 bridge has to be * approved as a spender. */ diff --git a/packages/contracts/contracts/gateway/GraphTokenGateway.sol b/packages/contracts/contracts/gateway/GraphTokenGateway.sol index fb992afc2..81edb9922 100644 --- a/packages/contracts/contracts/gateway/GraphTokenGateway.sol +++ b/packages/contracts/contracts/gateway/GraphTokenGateway.sol @@ -3,13 +3,14 @@ pragma solidity ^0.7.6; import { GraphUpgradeable } from "../upgrades/GraphUpgradeable.sol"; -import { ITokenGateway } from "../arbitrum/ITokenGateway.sol"; +import { ITokenGateway } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol"; import { Pausable } from "../governance/Pausable.sol"; import { Managed } from "../governance/Managed.sol"; /** * @title L1/L2 Graph Token Gateway - * @dev This includes everything that's shared between the L1 and L2 sides of the bridge. + * @author Edge & Node + * @notice This includes everything that's shared between the L1 and L2 sides of the bridge. */ abstract contract GraphTokenGateway is GraphUpgradeable, Pausable, Managed, ITokenGateway { /// @dev Storage gap added in case we need to add state variables to this contract @@ -52,7 +53,7 @@ abstract contract GraphTokenGateway is GraphUpgradeable, Pausable, Managed, ITok } /** - * @dev Override the default pausing from Managed to allow pausing this + * @notice Override the default pausing from Managed to allow pausing this * particular contract instead of pausing from the Controller. */ function _notPaused() internal view override { @@ -60,7 +61,7 @@ abstract contract GraphTokenGateway is GraphUpgradeable, Pausable, Managed, ITok } /** - * @dev Runs state validation before unpausing, reverts if + * @notice Runs state validation before unpausing, reverts if * something is not set properly */ function _checksBeforeUnpause() internal view virtual; diff --git a/packages/contracts/contracts/gateway/ICallhookReceiver.sol b/packages/contracts/contracts/gateway/ICallhookReceiver.sol deleted file mode 100644 index 8d003cb76..000000000 --- a/packages/contracts/contracts/gateway/ICallhookReceiver.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -/** - * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge - * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must - * be allowlisted by the governor, but also implement this interface that contains - * the function that will actually be called by the L2GraphTokenGateway. - */ -pragma solidity ^0.7.6 || 0.8.27; - -interface ICallhookReceiver { - /** - * @notice Receive tokens with a callhook from the bridge - * @param _from Token sender in L1 - * @param _amount Amount of tokens that were transferred - * @param _data ABI-encoded callhook data - */ - function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external; -} diff --git a/packages/contracts/contracts/gateway/L1GraphTokenGateway.sol b/packages/contracts/contracts/gateway/L1GraphTokenGateway.sol index 7fad927ad..d9216b956 100644 --- a/packages/contracts/contracts/gateway/L1GraphTokenGateway.sol +++ b/packages/contracts/contracts/gateway/L1GraphTokenGateway.sol @@ -3,22 +3,27 @@ pragma solidity ^0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events, gas-strict-inequalities +// solhint-disable named-parameters-mapping + import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol"; import { AddressUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import { SafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import { L1ArbitrumMessenger } from "../arbitrum/L1ArbitrumMessenger.sol"; -import { IBridge } from "../arbitrum/IBridge.sol"; -import { IInbox } from "../arbitrum/IInbox.sol"; -import { IOutbox } from "../arbitrum/IOutbox.sol"; -import { ITokenGateway } from "../arbitrum/ITokenGateway.sol"; +import { IBridge } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/IBridge.sol"; +import { IInbox } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/IInbox.sol"; +import { IOutbox } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/IOutbox.sol"; +import { ITokenGateway } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol"; import { Managed } from "../governance/Managed.sol"; import { GraphTokenGateway } from "./GraphTokenGateway.sol"; -import { IGraphToken } from "../token/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; /** * @title L1 Graph Token Gateway Contract - * @dev Provides the L1 side of the Ethereum-Arbitrum GRT bridge. Sends GRT to the L2 chain + * @author Edge & Node + * @notice Provides the L1 side of the Ethereum-Arbitrum GRT bridge. Sends GRT to the L2 chain * by escrowing them and sending a message to the L2 gateway, and receives tokens from L2 by * releasing them from escrow. * Based on Offchain Labs' reference implementation and Livepeer's arbitrum-lpt-bridge @@ -28,28 +33,35 @@ import { IGraphToken } from "../token/IGraphToken.sol"; contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMessenger { using SafeMathUpgradeable for uint256; - /// Address of the Graph Token contract on L2 + /// @notice Address of the Graph Token contract on L2 address public l2GRT; - /// Address of the Arbitrum Inbox + /// @notice Address of the Arbitrum Inbox address public inbox; - /// Address of the Arbitrum Gateway Router on L1 + /// @notice Address of the Arbitrum Gateway Router on L1 address public l1Router; - /// Address of the L2GraphTokenGateway on L2 that is the counterpart of this gateway + /// @notice Address of the L2GraphTokenGateway on L2 that is the counterpart of this gateway address public l2Counterpart; - /// Address of the BridgeEscrow contract that holds the GRT in the bridge + /// @notice Address of the BridgeEscrow contract that holds the GRT in the bridge address public escrow; - /// Addresses for which this mapping is true are allowed to send callhooks in outbound transfers + /// @notice Addresses for which this mapping is true are allowed to send callhooks in outbound transfers mapping(address => bool) public callhookAllowlist; - /// Total amount minted from L2 + /// @notice Total amount minted from L2 uint256 public totalMintedFromL2; - /// Accumulated allowance for tokens minted from L2 at lastL2MintAllowanceUpdateBlock + /// @notice Accumulated allowance for tokens minted from L2 at lastL2MintAllowanceUpdateBlock uint256 public accumulatedL2MintAllowanceSnapshot; - /// Block at which new L2 allowance starts accumulating + /// @notice Block at which new L2 allowance starts accumulating uint256 public lastL2MintAllowanceUpdateBlock; - /// New L2 mint allowance per block + /// @notice New L2 mint allowance per block uint256 public l2MintAllowancePerBlock; - /// Emitted when an outbound transfer is initiated, i.e. tokens are deposited from L1 to L2 + /** + * @notice Emitted when an outbound transfer is initiated, i.e. tokens are deposited from L1 to L2 + * @param l1Token Address of the L1 token being transferred + * @param from Address sending the tokens on L1 + * @param to Address receiving the tokens on L2 + * @param sequenceNumber Sequence number of the retryable ticket + * @param amount Amount of tokens transferred + */ event DepositInitiated( address l1Token, address indexed from, @@ -58,7 +70,14 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess uint256 amount ); - /// Emitted when an incoming transfer is finalized, i.e tokens are withdrawn from L2 to L1 + /** + * @notice Emitted when an incoming transfer is finalized, i.e tokens are withdrawn from L2 to L1 + * @param l1Token Address of the L1 token being transferred + * @param from Address sending the tokens on L2 + * @param to Address receiving the tokens on L1 + * @param exitNum Exit number (always 0 for this contract) + * @param amount Amount of tokens transferred + */ event WithdrawalFinalized( address l1Token, address indexed from, @@ -67,25 +86,58 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess uint256 amount ); - /// Emitted when the Arbitrum Inbox and Gateway Router addresses have been updated + /** + * @notice Emitted when the Arbitrum Inbox and Gateway Router addresses have been updated + * @param inbox Address of the Arbitrum Inbox + * @param l1Router Address of the L1 Gateway Router + */ event ArbitrumAddressesSet(address inbox, address l1Router); - /// Emitted when the L2 GRT address has been updated + + /** + * @notice Emitted when the L2 GRT address has been updated + * @param l2GRT Address of the L2 GRT contract + */ event L2TokenAddressSet(address l2GRT); - /// Emitted when the counterpart L2GraphTokenGateway address has been updated + + /** + * @notice Emitted when the counterpart L2GraphTokenGateway address has been updated + * @param l2Counterpart Address of the L2 counterpart gateway + */ event L2CounterpartAddressSet(address l2Counterpart); - /// Emitted when the escrow address has been updated + /** + * @notice Emitted when the escrow address has been updated + * @param escrow Address of the escrow contract + */ event EscrowAddressSet(address escrow); - /// Emitted when an address is added to the callhook allowlist + + /** + * @notice Emitted when an address is added to the callhook allowlist + * @param newAllowlisted Address added to the allowlist + */ event AddedToCallhookAllowlist(address newAllowlisted); - /// Emitted when an address is removed from the callhook allowlist + + /** + * @notice Emitted when an address is removed from the callhook allowlist + * @param notAllowlisted Address removed from the allowlist + */ event RemovedFromCallhookAllowlist(address notAllowlisted); - /// Emitted when the L2 mint allowance per block is updated + + /** + * @notice Emitted when the L2 mint allowance per block is updated + * @param accumulatedL2MintAllowanceSnapshot Accumulated allowance snapshot at update block + * @param l2MintAllowancePerBlock New allowance per block + * @param lastL2MintAllowanceUpdateBlock Block number when allowance was updated + */ event L2MintAllowanceUpdated( uint256 accumulatedL2MintAllowanceSnapshot, uint256 l2MintAllowancePerBlock, uint256 lastL2MintAllowanceUpdateBlock ); - /// Emitted when tokens are minted due to an incoming transfer from L2 + + /** + * @notice Emitted when tokens are minted due to an incoming transfer from L2 + * @param amount Amount of tokens minted + */ event TokensMintedFromL2(uint256 amount); /** @@ -199,7 +251,7 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess } /** - * @dev Updates the L2 mint allowance per block + * @notice Updates the L2 mint allowance per block * It is meant to be called _after_ the issuancePerBlock is updated in L2. * The caller should provide the new issuance per block and the block at which it was updated, * the function will automatically compute the values so that the bridge's mint allowance @@ -221,7 +273,7 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess } /** - * @dev Manually sets the parameters used to compute the L2 mint allowance + * @notice Manually sets the parameters used to compute the L2 mint allowance * The use of this function is not recommended, use updateL2MintAllowance instead; * this one is only meant to be used as a backup recovery if a previous call to * updateL2MintAllowance was done with incorrect values. @@ -246,10 +298,7 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess } /** - * @notice Creates and sends a retryable ticket to transfer GRT to L2 using the Arbitrum Inbox. - * The tokens are escrowed by the gateway until they are withdrawn back to L1. - * The ticket must be redeemed on L2 to receive tokens at the specified address. - * Note that the caller must previously allow the gateway to spend the specified amount of GRT. + * @inheritdoc ITokenGateway * @dev maxGas and gasPriceBid must be set using Arbitrum's NodeInterface.estimateRetryableTicket method. * Also note that allowlisted senders (some protocol contracts) can include additional calldata * for a callhook to be executed on the L2 side when the tokens are received. In this case, the L2 transaction @@ -257,13 +306,6 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess * never succeeds. This requires extra care when adding contracts to the allowlist, but is necessary to ensure that * the tickets can be retried in the case of a temporary failure, and to ensure the atomicity of callhooks * with token transfers. - * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router) - * @param _to Recipient address on L2 - * @param _amount Amount of tokens to transfer - * @param _maxGas Gas limit for L2 execution of the ticket - * @param _gasPriceBid Price per gas on L2 - * @param _data Encoded maxSubmissionCost and sender address along with additional calldata - * @return Sequence number of the retryable ticket created by Inbox */ function outboundTransfer( address _l1Token, @@ -304,15 +346,10 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess } /** - * @notice Receives withdrawn tokens from L2 - * The equivalent tokens are released from escrow and sent to the destination. + * @inheritdoc ITokenGateway * @dev can only accept transactions coming from the L2 GRT Gateway. * The last parameter is unused but kept for compatibility with Arbitrum gateways, * and the encoded exitNum is assumed to be 0. - * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router) - * @param _from Address of the sender - * @param _to Recipient address on L1 - * @param _amount Amount of tokens transferred */ function finalizeInboundTransfer( address _l1Token, @@ -335,10 +372,8 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess } /** - * @notice Calculate the L2 address of a bridged token + * @inheritdoc ITokenGateway * @dev In our case, this would only work for GRT. - * @param _l1ERC20 address of L1 GRT contract - * @return L2 address of the bridged GRT token */ function calculateL2TokenAddress(address _l1ERC20) external view override returns (address) { IGraphToken token = graphToken(); @@ -387,10 +422,8 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess ); } - /** - * @dev Runs state validation before unpausing, reverts if - * something is not set properly - */ + /// @inheritdoc GraphTokenGateway + // solhint-disable-next-line use-natspec function _checksBeforeUnpause() internal view override { require(inbox != address(0), "INBOX_NOT_SET"); require(l1Router != address(0), "ROUTER_NOT_SET"); @@ -425,7 +458,7 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess } /** - * @dev Get the accumulated L2 mint allowance at a particular block number + * @notice Get the accumulated L2 mint allowance at a particular block number * @param _blockNum Block at which allowance will be computed * @return The accumulated GRT amount that can be minted from L2 at the specified block */ @@ -438,7 +471,7 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess } /** - * @dev Mint new L1 tokens coming from L2 + * @notice Mint new L1 tokens coming from L2 * This will check if the amount to mint is within the L2's mint allowance, and revert otherwise. * The tokens will be sent to the bridge escrow (from where they will then be sent to the destinatary * of the current inbound transfer). @@ -454,7 +487,7 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess } /** - * @dev Check if minting a certain amount of tokens from L2 is within allowance + * @notice Check if minting a certain amount of tokens from L2 is within allowance * @param _amount Number of tokens that would be minted * @return true if minting those tokens is allowed, or false if it would be over allowance */ diff --git a/packages/contracts/contracts/governance/Controller.sol b/packages/contracts/contracts/governance/Controller.sol index 707a27fff..c850542ab 100644 --- a/packages/contracts/contracts/governance/Controller.sol +++ b/packages/contracts/contracts/governance/Controller.sol @@ -2,21 +2,32 @@ pragma solidity ^0.7.6 || 0.8.27; -import { IController } from "./IController.sol"; -import { IManaged } from "./IManaged.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events, gas-small-strings +// solhint-disable named-parameters-mapping + +/* solhint-disable gas-custom-errors */ // Cannot use custom errors with 0.7.6 + +import { IController } from "@graphprotocol/interfaces/contracts/contracts/governance/IController.sol"; +import { IManaged } from "@graphprotocol/interfaces/contracts/contracts/governance/IManaged.sol"; import { Governed } from "./Governed.sol"; import { Pausable } from "./Pausable.sol"; /** * @title Graph Controller contract - * @dev Controller is a registry of contracts for convenience. Inspired by Livepeer: + * @author Edge & Node + * @notice Controller is a registry of contracts for convenience. Inspired by Livepeer: * https://github.com/livepeer/protocol/blob/streamflow/contracts/Controller.sol */ contract Controller is Governed, Pausable, IController { /// @dev Track contract ids to contract proxy address mapping(bytes32 => address) private _registry; - /// Emitted when the proxy address for a protocol contract has been set + /** + * @notice Emitted when the proxy address for a protocol contract has been set + * @param id Contract identifier + * @param contractAddress Address of the contract proxy + */ event SetContractProxy(bytes32 indexed id, address contractAddress); /** @@ -37,7 +48,7 @@ contract Controller is Governed, Pausable, IController { } /** - * @notice Getter to access governor + * @inheritdoc IController */ function getGovernor() external view override returns (address) { return governor; @@ -46,9 +57,7 @@ contract Controller is Governed, Pausable, IController { // -- Registry -- /** - * @notice Register contract id and mapped address - * @param _id Contract id (keccak256 hash of contract name) - * @param _contractAddress Contract address + * @inheritdoc IController */ function setContractProxy(bytes32 _id, address _contractAddress) external override onlyGovernor { require(_contractAddress != address(0), "Contract address must be set"); @@ -57,8 +66,7 @@ contract Controller is Governed, Pausable, IController { } /** - * @notice Unregister a contract address - * @param _id Contract id (keccak256 hash of contract name) + * @inheritdoc IController */ function unsetContractProxy(bytes32 _id) external override onlyGovernor { _registry[_id] = address(0); @@ -66,18 +74,14 @@ contract Controller is Governed, Pausable, IController { } /** - * @notice Get contract proxy address by its id - * @param _id Contract id - * @return Address of the proxy contract for the provided id + * @inheritdoc IController */ function getContractProxy(bytes32 _id) external view override returns (address) { return _registry[_id]; } /** - * @notice Update contract's controller - * @param _id Contract id (keccak256 hash of contract name) - * @param _controller Controller address + * @inheritdoc IController */ function updateController(bytes32 _id, address _controller) external override onlyGovernor { require(_controller != address(0), "Controller must be set"); @@ -96,17 +100,15 @@ contract Controller is Governed, Pausable, IController { } /** - * @notice Change the paused state of the contract - * Full pause most of protocol functions - * @param _toPause True if the contracts should be paused, false otherwise + * @inheritdoc IController + * @dev Full pause most of protocol functions */ function setPaused(bool _toPause) external override onlyGovernorOrGuardian { _setPaused(_toPause); } /** - * @notice Change the Pause Guardian - * @param _newPauseGuardian The address of the new Pause Guardian + * @inheritdoc IController */ function setPauseGuardian(address _newPauseGuardian) external override onlyGovernor { require(_newPauseGuardian != address(0), "PauseGuardian must be set"); @@ -114,16 +116,14 @@ contract Controller is Governed, Pausable, IController { } /** - * @notice Getter to access paused - * @return True if the contracts are paused, false otherwise + * @inheritdoc IController */ function paused() external view override returns (bool) { return _paused; } /** - * @notice Getter to access partial pause status - * @return True if the contracts are partially paused, false otherwise + * @inheritdoc IController */ function partialPaused() external view override returns (bool) { return _partialPaused; diff --git a/packages/contracts/contracts/governance/Governed.sol b/packages/contracts/contracts/governance/Governed.sol index 76a3247dd..8c3446b88 100644 --- a/packages/contracts/contracts/governance/Governed.sol +++ b/packages/contracts/contracts/governance/Governed.sol @@ -2,23 +2,39 @@ pragma solidity ^0.7.6 || 0.8.27; +/* solhint-disable gas-custom-errors */ // Cannot use custom errors with 0.7.6 + /** * @title Graph Governance contract - * @dev All contracts that will be owned by a Governor entity should extend this contract. + * @author Edge & Node + * @notice All contracts that will be owned by a Governor entity should extend this contract. */ abstract contract Governed { // -- State -- - /// Address of the governor + /** + * @notice Address of the governor + */ address public governor; - /// Address of the new governor that is pending acceptance + /** + * @notice Address of the new governor that is pending acceptance + */ address public pendingGovernor; // -- Events -- - /// Emitted when a new owner/governor has been set, but is pending acceptance + /** + * @notice Emitted when a new owner/governor has been set, but is pending acceptance + * @param from Previous pending governor address + * @param to New pending governor address + */ event NewPendingOwnership(address indexed from, address indexed to); - /// Emitted when a new owner/governor has accepted their role + + /** + * @notice Emitted when a new owner/governor has accepted their role + * @param from Previous governor address + * @param to New governor address + */ event NewOwnership(address indexed from, address indexed to); /** @@ -30,7 +46,7 @@ abstract contract Governed { } /** - * @dev Initialize the governor for this contract + * @notice Initialize the governor for this contract * @param _initGovernor Address of the governor */ function _initialize(address _initGovernor) internal { diff --git a/packages/contracts/contracts/governance/IController.sol b/packages/contracts/contracts/governance/IController.sol deleted file mode 100644 index 6ab72010e..000000000 --- a/packages/contracts/contracts/governance/IController.sol +++ /dev/null @@ -1,29 +0,0 @@ -// 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); -} diff --git a/packages/contracts/contracts/governance/IManaged.sol b/packages/contracts/contracts/governance/IManaged.sol deleted file mode 100644 index ff6625d81..000000000 --- a/packages/contracts/contracts/governance/IManaged.sol +++ /dev/null @@ -1,32 +0,0 @@ -// 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); -} diff --git a/packages/contracts/contracts/governance/Managed.sol b/packages/contracts/contracts/governance/Managed.sol index 9b0ea29c8..c4718a1e6 100644 --- a/packages/contracts/contracts/governance/Managed.sol +++ b/packages/contracts/contracts/governance/Managed.sol @@ -2,21 +2,26 @@ pragma solidity ^0.7.6; -import { IController } from "./IController.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events +// solhint-disable named-parameters-mapping -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 { IController } from "@graphprotocol/interfaces/contracts/contracts/governance/IController.sol"; -import { IManaged } from "./IManaged.sol"; +import { ICuration } from "@graphprotocol/interfaces/contracts/contracts/curation/ICuration.sol"; +import { IEpochManager } from "@graphprotocol/interfaces/contracts/contracts/epochs/IEpochManager.sol"; +import { IRewardsManager } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsManager.sol"; +import { IStaking } from "@graphprotocol/interfaces/contracts/contracts/staking/IStaking.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; +import { ITokenGateway } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol"; +import { IGNS } from "@graphprotocol/interfaces/contracts/contracts/discovery/IGNS.sol"; + +import { IManaged } from "@graphprotocol/interfaces/contracts/contracts/governance/IManaged.sol"; /** * @title Graph Managed contract - * @dev The Managed contract provides an interface to interact with the Controller. + * @author Edge & Node + * @notice 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. * @@ -26,7 +31,9 @@ import { IManaged } from "./IManaged.sol"; abstract contract Managed is IManaged { // -- State -- - /// Controller that manages this contract + /** + * @inheritdoc IManaged + */ IController public override controller; /// @dev Cache for the addresses of the contracts retrieved from the controller mapping(bytes32 => address) private _addressCache; @@ -34,28 +41,46 @@ abstract contract Managed is IManaged { uint256[10] private __gap; // Immutables + /// @dev Contract name hash for Curation contract bytes32 private immutable CURATION = keccak256("Curation"); + /// @dev Contract name hash for EpochManager contract bytes32 private immutable EPOCH_MANAGER = keccak256("EpochManager"); + /// @dev Contract name hash for RewardsManager contract bytes32 private immutable REWARDS_MANAGER = keccak256("RewardsManager"); + /// @dev Contract name hash for Staking contract bytes32 private immutable STAKING = keccak256("Staking"); + /// @dev Contract name hash for GraphToken contract bytes32 private immutable GRAPH_TOKEN = keccak256("GraphToken"); + /// @dev Contract name hash for GraphTokenGateway contract bytes32 private immutable GRAPH_TOKEN_GATEWAY = keccak256("GraphTokenGateway"); + /// @dev Contract name hash for GNS contract bytes32 private immutable GNS = keccak256("GNS"); // -- Events -- - /// Emitted when a contract parameter has been updated + /** + * @notice Emitted when a contract parameter has been updated + * @param param Name of the parameter that was updated + */ event ParameterUpdated(string param); - /// Emitted when the controller address has been set + + /** + * @notice Emitted when the controller address has been set + * @param controller Address of the new controller + */ event SetController(address controller); - /// Emitted when contract with `nameHash` is synced to `contractAddress`. + /** + * @notice Emitted when contract with `nameHash` is synced to `contractAddress`. + * @param nameHash Hash of the contract name + * @param contractAddress Address of the synced contract + */ event ContractSynced(bytes32 indexed nameHash, address contractAddress); // -- Modifiers -- /** - * @dev Revert if the controller is paused or partially paused + * @notice Revert if the controller is paused or partially paused */ function _notPartialPaused() internal view { require(!controller.paused(), "Paused"); @@ -63,21 +88,21 @@ abstract contract Managed is IManaged { } /** - * @dev Revert if the controller is paused + * @notice Revert if the controller is paused */ function _notPaused() internal view virtual { require(!controller.paused(), "Paused"); } /** - * @dev Revert if the caller is not the governor + * @notice 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 + * @notice Revert if the caller is not the Controller */ function _onlyController() internal view { require(msg.sender == address(controller), "Caller must be Controller"); @@ -118,7 +143,7 @@ abstract contract Managed is IManaged { // -- Functions -- /** - * @dev Initialize a Managed contract + * @notice Initialize a Managed contract * @param _controller Address for the Controller that manages this contract */ function _initialize(address _controller) internal { @@ -126,15 +151,14 @@ abstract contract Managed is IManaged { } /** - * @notice Set Controller. Only callable by current controller. - * @param _controller Controller contract address + * @inheritdoc IManaged */ function setController(address _controller) external override onlyController { _setController(_controller); } /** - * @dev Set controller. + * @notice Set controller. * @param _controller Controller contract address */ function _setController(address _controller) internal { @@ -144,7 +168,7 @@ abstract contract Managed is IManaged { } /** - * @dev Return Curation interface + * @notice Return Curation interface * @return Curation contract registered with Controller */ function curation() internal view returns (ICuration) { @@ -152,7 +176,7 @@ abstract contract Managed is IManaged { } /** - * @dev Return EpochManager interface + * @notice Return EpochManager interface * @return Epoch manager contract registered with Controller */ function epochManager() internal view returns (IEpochManager) { @@ -160,7 +184,7 @@ abstract contract Managed is IManaged { } /** - * @dev Return RewardsManager interface + * @notice Return RewardsManager interface * @return Rewards manager contract registered with Controller */ function rewardsManager() internal view returns (IRewardsManager) { @@ -168,7 +192,7 @@ abstract contract Managed is IManaged { } /** - * @dev Return Staking interface + * @notice Return Staking interface * @return Staking contract registered with Controller */ function staking() internal view returns (IStaking) { @@ -176,7 +200,7 @@ abstract contract Managed is IManaged { } /** - * @dev Return GraphToken interface + * @notice Return GraphToken interface * @return Graph token contract registered with Controller */ function graphToken() internal view returns (IGraphToken) { @@ -184,7 +208,7 @@ abstract contract Managed is IManaged { } /** - * @dev Return GraphTokenGateway (L1 or L2) interface + * @notice Return GraphTokenGateway (L1 or L2) interface * @return Graph token gateway contract registered with Controller */ function graphTokenGateway() internal view returns (ITokenGateway) { @@ -192,7 +216,7 @@ abstract contract Managed is IManaged { } /** - * @dev Return GNS (L1 or L2) interface. + * @notice 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) { @@ -200,7 +224,7 @@ abstract contract Managed is IManaged { } /** - * @dev Resolve a contract address from the cache or the Controller if not found. + * @notice 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 */ @@ -213,7 +237,7 @@ abstract contract Managed is IManaged { } /** - * @dev Cache a contract address from the Controller registry. + * @notice 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 { @@ -225,10 +249,7 @@ abstract contract Managed is IManaged { } /** - * @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 + * @inheritdoc IManaged */ function syncAllContracts() external override { _syncContract(CURATION); diff --git a/packages/contracts/contracts/governance/Pausable.sol b/packages/contracts/contracts/governance/Pausable.sol index 2bc1795cd..bf260cb72 100644 --- a/packages/contracts/contracts/governance/Pausable.sol +++ b/packages/contracts/contracts/governance/Pausable.sol @@ -2,6 +2,14 @@ pragma solidity ^0.7.6 || 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events + +/** + * @title Pausable Contract + * @author Edge & Node + * @notice Abstract contract that provides pause functionality for protocol operations + */ abstract contract Pausable { /** * @dev "Partial paused" pauses exit and enter functions for GRT, but not internal @@ -13,24 +21,36 @@ abstract contract Pausable { */ bool internal _paused; - /// Timestamp for the last time the partial pause was set + /// @notice Timestamp for the last time the partial pause was set uint256 public lastPartialPauseTime; - /// Timestamp for the last time the full pause was set + /// @notice Timestamp for the last time the full pause was set uint256 public lastPauseTime; - /// Pause guardian is a separate entity from the governor that can + /// @notice Pause guardian is a separate entity from the governor that can /// pause and unpause the protocol, fully or partially address public pauseGuardian; - /// Emitted when the partial pause state changed + /** + * @notice Emitted when the partial pause state changed + * @param isPaused Whether the contract is partially paused + */ event PartialPauseChanged(bool isPaused); - /// Emitted when the full pause state changed + + /** + * @notice Emitted when the full pause state changed + * @param isPaused Whether the contract is fully paused + */ event PauseChanged(bool isPaused); - /// Emitted when the pause guardian is changed + + /** + * @notice Emitted when the pause guardian is changed + * @param oldPauseGuardian Address of the previous pause guardian + * @param pauseGuardian Address of the new pause guardian + */ event NewPauseGuardian(address indexed oldPauseGuardian, address indexed pauseGuardian); /** - * @dev Change the partial paused state of the contract + * @notice Change the partial paused state of the contract * @param _toPartialPause New value for the partial pause state (true means the contracts will be partially paused) */ function _setPartialPaused(bool _toPartialPause) internal { @@ -45,7 +65,7 @@ abstract contract Pausable { } /** - * @dev Change the paused state of the contract + * @notice Change the paused state of the contract * @param _toPause New value for the pause state (true means the contracts will be paused) */ function _setPaused(bool _toPause) internal { @@ -60,7 +80,7 @@ abstract contract Pausable { } /** - * @dev Change the Pause Guardian + * @notice Change the Pause Guardian * @param newPauseGuardian The address of the new Pause Guardian */ function _setPauseGuardian(address newPauseGuardian) internal { diff --git a/packages/contracts/contracts/l2/curation/IL2Curation.sol b/packages/contracts/contracts/l2/curation/IL2Curation.sol deleted file mode 100644 index 7f93f9603..000000000 --- a/packages/contracts/contracts/l2/curation/IL2Curation.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity ^0.7.6 || 0.8.27; - -/** - * @title Interface of the L2 Curation contract. - */ -interface IL2Curation { - /** - * @notice Set the subgraph service address. - * @param _subgraphService Address of the SubgraphService contract - */ - function setSubgraphService(address _subgraphService) external; - - /** - * @notice Deposit Graph Tokens in exchange for signal of a SubgraphDeployment curation pool. - * @dev This function charges no tax and can only be called by GNS in specific scenarios (for now - * only during an L1-L2 transfer). - * @param _subgraphDeploymentID Subgraph deployment pool from where to mint signal - * @param _tokensIn Amount of Graph Tokens to deposit - * @return Signal minted - */ - function mintTaxFree(bytes32 _subgraphDeploymentID, uint256 _tokensIn) external returns (uint256); - - /** - * @notice Calculate amount of signal that can be bought with tokens in a curation pool, - * without accounting for curation tax. - * @param _subgraphDeploymentID Subgraph deployment for which to mint signal - * @param _tokensIn Amount of tokens used to mint signal - * @return Amount of signal that can be bought - */ - function tokensToSignalNoTax(bytes32 _subgraphDeploymentID, uint256 _tokensIn) external view returns (uint256); - - /** - * @notice Calculate the amount of tokens that would be recovered if minting signal with - * the input tokens and then burning it. This can be used to compute rounding error. - * This function does not account for curation tax. - * @param _subgraphDeploymentID Subgraph deployment for which to mint signal - * @param _tokensIn Amount of tokens used to mint signal - * @return Amount of tokens that would be recovered after minting and burning signal - */ - function tokensToSignalToTokensNoTax( - bytes32 _subgraphDeploymentID, - uint256 _tokensIn - ) external view returns (uint256); -} diff --git a/packages/contracts/contracts/l2/curation/L2Curation.sol b/packages/contracts/contracts/l2/curation/L2Curation.sol index 271545ea7..56e83c13a 100644 --- a/packages/contracts/contracts/l2/curation/L2Curation.sol +++ b/packages/contracts/contracts/l2/curation/L2Curation.sol @@ -3,22 +3,26 @@ pragma solidity ^0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events, gas-small-strings, gas-strict-inequalities + import { AddressUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import { SafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import { ClonesUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/ClonesUpgradeable.sol"; import { GraphUpgradeable } from "../../upgrades/GraphUpgradeable.sol"; import { TokenUtils } from "../../utils/TokenUtils.sol"; -import { IRewardsManager } from "../../rewards/IRewardsManager.sol"; +import { IRewardsManager } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsManager.sol"; import { Managed } from "../../governance/Managed.sol"; -import { IGraphToken } from "../../token/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { CurationV3Storage } from "../../curation/CurationStorage.sol"; -import { IGraphCurationToken } from "../../curation/IGraphCurationToken.sol"; -import { IL2Curation } from "./IL2Curation.sol"; +import { IGraphCurationToken } from "@graphprotocol/interfaces/contracts/contracts/curation/IGraphCurationToken.sol"; +import { IL2Curation } from "@graphprotocol/interfaces/contracts/contracts/l2/curation/IL2Curation.sol"; /** * @title L2Curation contract - * @dev Allows curators to signal on subgraph deployments that might be relevant to indexers by + * @author Edge & Node + * @notice Allows curators to signal on subgraph deployments that might be relevant to indexers by * staking Graph Tokens (GRT). Additionally, curators earn fees from the Query Market related to the * subgraph deployment they curate. * A curators deposit goes to a curation pool along with the deposits of other curators, @@ -38,14 +42,20 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { uint256 private constant SIGNAL_PER_MINIMUM_DEPOSIT = 1; // 1e-18 signal as 18 decimal number /// @dev Reserve ratio for all subgraphs set to 100% for a flat bonding curve + // solhint-disable-next-line immutable-vars-naming uint32 private immutable fixedReserveRatio = MAX_PPM; // -- Events -- /** - * @dev Emitted when `curator` deposited `tokens` on `subgraphDeploymentID` as curation signal. + * @notice Emitted when `curator` deposited `tokens` on `subgraphDeploymentID` as curation signal. * The `curator` receives `signal` amount according to the curation pool bonding curve. * An amount of `curationTax` will be collected and burned. + * @param curator Address of the curator + * @param subgraphDeploymentID Subgraph deployment being signaled on + * @param tokens Amount of tokens deposited + * @param signal Amount of signal minted + * @param curationTax Amount of tokens burned as curation tax */ event Signalled( address indexed curator, @@ -56,19 +66,26 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { ); /** - * @dev Emitted when `curator` burned `signal` for a `subgraphDeploymentID`. + * @notice Emitted when `curator` burned `signal` for a `subgraphDeploymentID`. * The curator will receive `tokens` according to the value of the bonding curve. + * @param curator Address of the curator + * @param subgraphDeploymentID Subgraph deployment being signaled on + * @param tokens Amount of tokens received + * @param signal Amount of signal burned */ event Burned(address indexed curator, bytes32 indexed subgraphDeploymentID, uint256 tokens, uint256 signal); /** - * @dev Emitted when `tokens` amount were collected for `subgraphDeploymentID` as part of fees + * @notice Emitted when `tokens` amount were collected for `subgraphDeploymentID` as part of fees * distributed by an indexer from query fees received from state channels. + * @param subgraphDeploymentID Subgraph deployment that collected fees + * @param tokens Amount of tokens collected as fees */ event Collected(bytes32 indexed subgraphDeploymentID, uint256 tokens); /** - * @dev Emitted when the subgraph service is set. + * @notice Emitted when the subgraph service is set + * @param newSubgraphService Address of the new subgraph service */ event SubgraphServiceSet(address indexed newSubgraphService); @@ -107,7 +124,8 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { * @notice Set the default reserve ratio - not implemented in L2 * @dev We only keep this for compatibility with ICuration */ - function setDefaultReserveRatio(uint32) external view override onlyGovernor { + // solhint-disable-next-line use-natspec + function setDefaultReserveRatio(uint32 /* _defaultReserveRatio */) external view override onlyGovernor { revert("Not implemented in L2"); } @@ -153,7 +171,7 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { * @param _tokens Amount of Graph Tokens to add to reserves */ function collect(bytes32 _subgraphDeploymentID, uint256 _tokens) external override { - // Only SubgraphService or Staking contract are authorized as caller + // Only SubgraphService and Staking contract are authorized as callers require( msg.sender == subgraphService || msg.sender == address(staking()), "Caller must be the subgraph service or staking contract" @@ -174,7 +192,8 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { * @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 Signal minted and deposit tax + * @return Signal minted + * @return Curation tax paid */ function mint( bytes32 _subgraphDeploymentID, @@ -228,12 +247,7 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { } /** - * @notice Deposit Graph Tokens in exchange for signal of a SubgraphDeployment curation pool. - * @dev This function charges no tax and can only be called by GNS in specific scenarios (for now - * only during an L1-L2 transfer). - * @param _subgraphDeploymentID Subgraph deployment pool from where to mint signal - * @param _tokensIn Amount of Graph Tokens to deposit - * @return Signal minted + * @inheritdoc IL2Curation */ function mintTaxFree( bytes32 _subgraphDeploymentID, @@ -387,11 +401,7 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { } /** - * @notice Calculate amount of signal that can be bought with tokens in a curation pool, - * without accounting for curation 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 + * @inheritdoc IL2Curation */ function tokensToSignalNoTax( bytes32 _subgraphDeploymentID, @@ -401,12 +411,7 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { } /** - * @notice Calculate the amount of tokens that would be recovered if minting signal with - * the input tokens and then burning it. This can be used to compute rounding error. - * This function does not account for curation tax. - * @param _subgraphDeploymentID Subgraph deployment for which to mint signal - * @param _tokensIn Amount of tokens used to mint signal - * @return Amount of tokens that would be recovered after minting and burning signal + * @inheritdoc IL2Curation */ function tokensToSignalToTokensNoTax( bytes32 _subgraphDeploymentID, @@ -436,7 +441,7 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { } /** - * @dev Internal: Set the minimum deposit amount for curators. + * @notice Internal: Set the minimum deposit amount for curators. * Update the minimum deposit amount to `_minimumCurationDeposit` * @param _minimumCurationDeposit Minimum amount of tokens required deposit */ @@ -448,7 +453,7 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { } /** - * @dev Internal: Set the curation tax percentage to charge when a curator deposits GRT tokens. + * @notice Internal: 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) private { @@ -459,7 +464,7 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { } /** - * @dev Internal: Set the master copy to use as clones for the curation token. + * @notice Internal: 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) private { @@ -471,7 +476,7 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { } /** - * @dev Triggers an update of rewards due to a change in signal. + * @notice Triggers an update of rewards due to a change in signal. * @param _subgraphDeploymentID Subgraph deployment updated */ function _updateRewards(bytes32 _subgraphDeploymentID) private { @@ -482,7 +487,7 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { } /** - * @dev Calculate amount of signal that can be bought with tokens in a curation pool. + * @notice Calculate amount of signal that can be bought with tokens in a curation pool. * @param _subgraphDeploymentID Subgraph deployment to mint signal * @param _tokensIn Amount of tokens used to mint signal * @return Amount of signal that can be bought with tokens diff --git a/packages/contracts/contracts/l2/discovery/IL2GNS.sol b/packages/contracts/contracts/l2/discovery/IL2GNS.sol deleted file mode 100644 index a24216fbb..000000000 --- a/packages/contracts/contracts/l2/discovery/IL2GNS.sol +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity ^0.7.6 || 0.8.27; - -import { ICallhookReceiver } from "../../gateway/ICallhookReceiver.sol"; - -/** - * @title Interface for the L2GNS contract. - */ -interface IL2GNS is ICallhookReceiver { - enum L1MessageCodes { - RECEIVE_SUBGRAPH_CODE, - RECEIVE_CURATOR_BALANCE_CODE - } - - /** - * @dev The SubgraphL2TransferData struct holds information - * about a subgraph related to its transfer from L1 to L2. - */ - struct SubgraphL2TransferData { - uint256 tokens; // GRT that will be sent to L2 to mint signal - mapping(address => bool) curatorBalanceClaimed; // True for curators whose balance has been claimed in L2 - bool l2Done; // Transfer finished on L2 side - uint256 subgraphReceivedOnL2BlockNumber; // Block number when the subgraph was received on L2 - } - - /** - * @notice Finish a subgraph transfer from L1. - * The subgraph must have been previously sent through the bridge - * using the sendSubgraphToL2 function on L1GNS. - * @param _l2SubgraphID Subgraph ID in L2 (aliased from the L1 subgraph ID) - * @param _subgraphDeploymentID Latest subgraph deployment to assign to the subgraph - * @param _subgraphMetadata IPFS hash of the subgraph metadata - * @param _versionMetadata IPFS hash of the version metadata - */ - function finishSubgraphTransferFromL1( - uint256 _l2SubgraphID, - bytes32 _subgraphDeploymentID, - bytes32 _subgraphMetadata, - bytes32 _versionMetadata - ) external; - - /** - * @notice Return the aliased L2 subgraph ID from a transferred L1 subgraph ID - * @param _l1SubgraphID L1 subgraph ID - * @return L2 subgraph ID - */ - function getAliasedL2SubgraphID(uint256 _l1SubgraphID) external pure returns (uint256); - - /** - * @notice Return the unaliased L1 subgraph ID from a transferred L2 subgraph ID - * @param _l2SubgraphID L2 subgraph ID - * @return L1subgraph ID - */ - function getUnaliasedL1SubgraphID(uint256 _l2SubgraphID) external pure returns (uint256); -} diff --git a/packages/contracts/contracts/l2/discovery/L2GNS.sol b/packages/contracts/contracts/l2/discovery/L2GNS.sol index 34d47d400..bd176dbcf 100644 --- a/packages/contracts/contracts/l2/discovery/L2GNS.sol +++ b/packages/contracts/contracts/l2/discovery/L2GNS.sol @@ -3,18 +3,22 @@ pragma solidity ^0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events, gas-small-strings, gas-strict-inequalities + import { SafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import { GNS } from "../../discovery/GNS.sol"; -import { ICuration } from "../../curation/ICuration.sol"; -import { IL2GNS } from "./IL2GNS.sol"; +import { ICuration } from "@graphprotocol/interfaces/contracts/contracts/curation/ICuration.sol"; +import { IL2GNS } from "@graphprotocol/interfaces/contracts/contracts/l2/discovery/IL2GNS.sol"; import { L2GNSV1Storage } from "./L2GNSStorage.sol"; -import { IL2Curation } from "../curation/IL2Curation.sol"; +import { IL2Curation } from "@graphprotocol/interfaces/contracts/contracts/l2/curation/IL2Curation.sol"; /** * @title L2GNS - * @dev The Graph Name System contract provides a decentralized naming system for subgraphs + * @author Edge & Node + * @notice The Graph Name System contract provides a decentralized naming system for subgraphs * used in the scope of the Graph Network. It translates Subgraphs into Subgraph Versions. * Each version is associated with a Subgraph Deployment. The contract has no knowledge of * human-readable names. All human readable names emitted in events. @@ -26,35 +30,47 @@ import { IL2Curation } from "../curation/IL2Curation.sol"; contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { using SafeMathUpgradeable for uint256; - /// Offset added to an L1 subgraph ID to compute the L2 subgraph ID alias + /// @notice Offset added to an L1 subgraph ID to compute the L2 subgraph ID alias uint256 public constant SUBGRAPH_ID_ALIAS_OFFSET = uint256(0x1111000000000000000000000000000000000000000000000000000000001111); - /// Maximum rounding error when receiving signal tokens from L1, in parts-per-million. - /// If the error from minting signal is above this, tokens will be sent back to the curator. + /// @notice Maximum rounding error when receiving signal tokens from L1, in parts-per-million + /// @dev If the error from minting signal is above this, tokens will be sent back to the curator uint256 public constant MAX_ROUNDING_ERROR = 1000; /// @dev 100% expressed in parts-per-million uint256 private constant MAX_PPM = 1000000; - /// @dev Emitted when a subgraph is received from L1 through the bridge + /// @notice Emitted when a subgraph is received from L1 through the bridge + /// @param _l1SubgraphID Subgraph ID on L1 + /// @param _l2SubgraphID Subgraph ID on L2 (aliased) + /// @param _owner Address of the subgraph owner + /// @param _tokens Amount of tokens transferred with the subgraph event SubgraphReceivedFromL1( uint256 indexed _l1SubgraphID, uint256 indexed _l2SubgraphID, address indexed _owner, uint256 _tokens ); - /// @dev Emitted when a subgraph transfer from L1 is finalized, so the subgraph is published on L2 + /// @notice Emitted when a subgraph transfer from L1 is finalized, so the subgraph is published on L2 + /// @param _l2SubgraphID Subgraph ID on L2 event SubgraphL2TransferFinalized(uint256 indexed _l2SubgraphID); - /// @dev Emitted when the L1 balance for a curator has been claimed + /// @notice Emitted when the L1 balance for a curator has been claimed + /// @param _l1SubgraphId Subgraph ID on L1 + /// @param _l2SubgraphID Subgraph ID on L2 (aliased) + /// @param _l2Curator Address of the curator on L2 + /// @param _tokens Amount of tokens received event CuratorBalanceReceived( uint256 indexed _l1SubgraphId, uint256 indexed _l2SubgraphID, address indexed _l2Curator, uint256 _tokens ); - /// @dev Emitted when the L1 balance for a curator has been returned to the beneficiary. + /// @notice Emitted when the L1 balance for a curator has been returned to the beneficiary. /// This can happen if the subgraph transfer was not finished when the curator's tokens arrived. + /// @param _l1SubgraphID Subgraph ID on L1 + /// @param _l2Curator Address of the curator on L2 + /// @param _tokens Amount of tokens returned event CuratorBalanceReturnedToBeneficiary( uint256 indexed _l1SubgraphID, address indexed _l2Curator, @@ -103,13 +119,7 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { } /** - * @notice Finish a subgraph transfer from L1. - * The subgraph must have been previously sent through the bridge - * using the sendSubgraphToL2 function on L1GNS. - * @param _l2SubgraphID Subgraph ID (aliased from the L1 subgraph ID) - * @param _subgraphDeploymentID Latest subgraph deployment to assign to the subgraph - * @param _subgraphMetadata IPFS hash of the subgraph metadata - * @param _versionMetadata IPFS hash of the version metadata + * @inheritdoc IL2GNS */ function finishSubgraphTransferFromL1( uint256 _l2SubgraphID, @@ -220,25 +230,21 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { } /** - * @notice Return the aliased L2 subgraph ID from a transferred L1 subgraph ID - * @param _l1SubgraphID L1 subgraph ID - * @return L2 subgraph ID + * @inheritdoc IL2GNS */ function getAliasedL2SubgraphID(uint256 _l1SubgraphID) public pure override returns (uint256) { return _l1SubgraphID + SUBGRAPH_ID_ALIAS_OFFSET; } /** - * @notice Return the unaliased L1 subgraph ID from a transferred L2 subgraph ID - * @param _l2SubgraphID L2 subgraph ID - * @return L1subgraph ID + * @inheritdoc IL2GNS */ function getUnaliasedL1SubgraphID(uint256 _l2SubgraphID) public pure override returns (uint256) { return _l2SubgraphID - SUBGRAPH_ID_ALIAS_OFFSET; } /** - * @dev Receive a subgraph from L1. + * @notice Receive a subgraph from L1. * This function will initialize a subgraph received through the bridge, * and store the transfer data so that it's finalized later using finishSubgraphTransferFromL1. * @param _l1SubgraphID Subgraph ID in L1 (will be aliased) @@ -308,9 +314,9 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { } /** - * @dev Get subgraph data. - * Since there are no legacy subgraphs in L2, we override the base - * GNS method to save us the step of checking for legacy subgraphs. + * @notice Get subgraph data + * @dev Since there are no legacy subgraphs in L2, we override the base + * GNS method to save us the step of checking for legacy subgraphs * @param _subgraphID Subgraph ID * @return Subgraph Data */ diff --git a/packages/contracts/contracts/l2/discovery/L2GNSStorage.sol b/packages/contracts/contracts/l2/discovery/L2GNSStorage.sol index f658c49d9..d464ea891 100644 --- a/packages/contracts/contracts/l2/discovery/L2GNSStorage.sol +++ b/packages/contracts/contracts/l2/discovery/L2GNSStorage.sol @@ -1,17 +1,20 @@ // SPDX-License-Identifier: GPL-2.0-or-later +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable named-parameters-mapping + pragma solidity ^0.7.6; pragma abicoder v2; -import { IL2GNS } from "./IL2GNS.sol"; +import { IL2GNS } from "@graphprotocol/interfaces/contracts/contracts/l2/discovery/IL2GNS.sol"; /** * @title L2GNSV1Storage + * @author Edge & Node * @notice This contract holds all the L2-specific storage variables for the L2GNS contract, version 1 - * @dev */ abstract contract L2GNSV1Storage { - /// Data for subgraph transfer from L1 to L2 + /// @notice Data for subgraph transfer from L1 to L2 mapping(uint256 => IL2GNS.SubgraphL2TransferData) public subgraphL2TransferData; /// @dev Storage gap to keep storage slots fixed in future versions uint256[50] private __gap; diff --git a/packages/contracts/contracts/l2/gateway/L2GraphTokenGateway.sol b/packages/contracts/contracts/l2/gateway/L2GraphTokenGateway.sol index be8f212b8..aa8868c49 100644 --- a/packages/contracts/contracts/l2/gateway/L2GraphTokenGateway.sol +++ b/packages/contracts/contracts/l2/gateway/L2GraphTokenGateway.sol @@ -3,20 +3,24 @@ pragma solidity ^0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events + import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { SafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import { L2ArbitrumMessenger } from "../../arbitrum/L2ArbitrumMessenger.sol"; import { AddressAliasHelper } from "../../arbitrum/AddressAliasHelper.sol"; -import { ITokenGateway } from "../../arbitrum/ITokenGateway.sol"; +import { ITokenGateway } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol"; import { Managed } from "../../governance/Managed.sol"; import { GraphTokenGateway } from "../../gateway/GraphTokenGateway.sol"; -import { ICallhookReceiver } from "../../gateway/ICallhookReceiver.sol"; +import { ICallhookReceiver } from "@graphprotocol/interfaces/contracts/contracts/gateway/ICallhookReceiver.sol"; import { L2GraphToken } from "../token/L2GraphToken.sol"; /** * @title L2 Graph Token Gateway Contract - * @dev Provides the L2 side of the Ethereum-Arbitrum GRT bridge. Receives GRT from the L1 chain + * @author Edge & Node + * @notice Provides the L2 side of the Ethereum-Arbitrum GRT bridge. Receives GRT from the L1 chain * and mints them on the L2 side. Sends GRT back to L1 by burning them on the L2 side. * Based on Offchain Labs' reference implementation and Livepeer's arbitrum-lpt-bridge * (See: https://github.com/OffchainLabs/arbitrum/tree/master/packages/arb-bridge-peripherals/contracts/tokenbridge @@ -25,23 +29,42 @@ import { L2GraphToken } from "../token/L2GraphToken.sol"; contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, ReentrancyGuardUpgradeable { using SafeMathUpgradeable for uint256; - /// Address of the Graph Token contract on L1 + /// @notice Address of the Graph Token contract on L1 address public l1GRT; - /// Address of the L1GraphTokenGateway that is the counterpart of this gateway on L1 + /// @notice Address of the L1GraphTokenGateway that is the counterpart of this gateway on L1 address public l1Counterpart; - /// Address of the Arbitrum Gateway Router on L2 + /// @notice Address of the Arbitrum Gateway Router on L2 address public l2Router; /// @dev Calldata included in an outbound transfer, stored as a structure for convenience and stack depth + /** + * @dev Struct for outbound transfer calldata + * @param from Address sending the tokens + * @param extraData Additional data for the transfer + */ struct OutboundCalldata { address from; bytes extraData; } - /// Emitted when an incoming transfer is finalized, i.e. tokens were deposited from L1 to L2 + /** + * @notice Emitted when an incoming transfer is finalized, i.e. tokens were deposited from L1 to L2 + * @param l1Token Address of the L1 token + * @param from Address sending the tokens on L1 + * @param to Address receiving the tokens on L2 + * @param amount Amount of tokens transferred + */ event DepositFinalized(address indexed l1Token, address indexed from, address indexed to, uint256 amount); - /// Emitted when an outbound transfer is initiated, i.e. tokens are being withdrawn from L2 back to L1 + /** + * @notice Emitted when an outbound transfer is initiated, i.e. tokens are being withdrawn from L2 back to L1 + * @param l1Token Address of the L1 token + * @param from Address sending the tokens on L2 + * @param to Address receiving the tokens on L1 + * @param l2ToL1Id ID of the L2 to L1 message + * @param exitNum Exit number (always 0 for this contract) + * @param amount Amount of tokens transferred + */ event WithdrawalInitiated( address l1Token, address indexed from, @@ -51,11 +74,22 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran uint256 amount ); - /// Emitted when the Arbitrum Gateway Router address on L2 has been updated + /** + * @notice Emitted when the Arbitrum Gateway Router address on L2 has been updated + * @param l2Router Address of the L2 Gateway Router + */ event L2RouterSet(address l2Router); - /// Emitted when the L1 Graph Token address has been updated + + /** + * @notice Emitted when the L1 Graph Token address has been updated + * @param l1GRT Address of the L1 GRT contract + */ event L1TokenAddressSet(address l1GRT); - /// Emitted when the address of the counterpart gateway on L1 has been updated + + /** + * @notice Emitted when the address of the counterpart gateway on L1 has been updated + * @param l1Counterpart Address of the L1 counterpart gateway + */ event L1CounterpartAddressSet(address l1Counterpart); /** @@ -135,7 +169,7 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran } /** - * @notice Receives token amount from L1 and mints the equivalent tokens to the receiving address + * @inheritdoc ITokenGateway * @dev Only accepts transactions from the L1 GRT Gateway. * The function is payable for ITokenGateway compatibility, but msg.value must be zero. * Note that allowlisted senders (some protocol contracts) can include additional calldata @@ -144,11 +178,6 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran * never succeeds. This requires extra care when adding contracts to the allowlist, but is necessary to ensure that * the tickets can be retried in the case of a temporary failure, and to ensure the atomicity of callhooks * with token transfers. - * @param _l1Token L1 Address of GRT - * @param _from Address of the sender on L1 - * @param _to Recipient address on L2 - * @param _amount Amount of tokens transferred - * @param _data Extra callhook data, only used when the sender is allowlisted */ function finalizeInboundTransfer( address _l1Token, @@ -170,18 +199,14 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran } /** - * @notice Burns L2 tokens and initiates a transfer to L1. + * @inheritdoc ITokenGateway + * @dev Burns L2 tokens and initiates a transfer to L1. * The tokens will be available on L1 only after the wait period (7 days) is over, * and will require an Outbox.executeTransaction to finalize. * Note that the caller must previously allow the gateway to spend the specified amount of GRT. - * @dev no additional callhook data is allowed. The two unused params are needed + * No additional callhook data is allowed. The two unused params are needed * for compatibility with Arbitrum's gateway router. * The function is payable for ITokenGateway compatibility, but msg.value must be zero. - * @param _l1Token L1 Address of GRT (needed for compatibility with Arbitrum Gateway Router) - * @param _to Recipient address on L1 - * @param _amount Amount of tokens to burn - * @param _data Contains sender and additional data (always empty) to send to L1 - * @return ID of the withdraw transaction */ function outboundTransfer( address _l1Token, @@ -218,10 +243,8 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran } /** - * @notice Calculate the L2 address of a bridged token + * @inheritdoc ITokenGateway * @dev In our case, this would only work for GRT. - * @param l1ERC20 address of L1 GRT contract - * @return L2 address of the bridged GRT token */ function calculateL2TokenAddress(address l1ERC20) public view override returns (address) { if (l1ERC20 != l1GRT) { @@ -259,10 +282,8 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran ); } - /** - * @dev Runs state validation before unpausing, reverts if - * something is not set properly - */ + /// @inheritdoc GraphTokenGateway + // solhint-disable-next-line use-natspec function _checksBeforeUnpause() internal view override { require(l2Router != address(0), "L2_ROUTER_NOT_SET"); require(l1Counterpart != address(0), "L1_COUNTERPART_NOT_SET"); diff --git a/packages/contracts/contracts/l2/staking/IL2Staking.sol b/packages/contracts/contracts/l2/staking/IL2Staking.sol deleted file mode 100644 index 4b7748e31..000000000 --- a/packages/contracts/contracts/l2/staking/IL2Staking.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity >=0.6.12 <0.8.0; -pragma abicoder v2; - -import { IStaking } from "../../staking/IStaking.sol"; -import { IL2StakingBase } from "./IL2StakingBase.sol"; -import { IL2StakingTypes } from "./IL2StakingTypes.sol"; - -/** - * @title Interface for the L2 Staking contract - * @notice This is the interface that should be used when interacting with the L2 Staking contract. - * It extends the IStaking interface with the functions that are specific to L2, adding the callhook receiver - * to receive transferred stake and delegation from L1. - * @dev Note that L2Staking 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 IL2Staking is IStaking, IL2StakingBase, IL2StakingTypes {} diff --git a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol deleted file mode 100644 index f5c33c2d0..000000000 --- a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity ^0.7.6 || 0.8.27; - -import { ICallhookReceiver } from "../../gateway/ICallhookReceiver.sol"; - -/** - * @title Base interface for the L2Staking contract. - * @notice This interface is used to define the callhook receiver interface that is implemented by L2Staking. - * @dev Note it includes only the L2-specific functionality, not the full IStaking interface. - */ -interface IL2StakingBase is ICallhookReceiver { - event TransferredDelegationReturnedToDelegator(address indexed indexer, address indexed delegator, uint256 amount); -} diff --git a/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol b/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol deleted file mode 100644 index 500694e89..000000000 --- a/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity ^0.7.6 || 0.8.27; - -interface IL2StakingTypes { - /// @dev Message codes for the L1 -> L2 bridge callhook - enum L1MessageCodes { - RECEIVE_INDEXER_STAKE_CODE, - RECEIVE_DELEGATION_CODE - } - - /// @dev Encoded message struct when receiving indexer stake through the bridge - struct ReceiveIndexerStakeData { - address indexer; - } - - /// @dev Encoded message struct when receiving delegation through the bridge - struct ReceiveDelegationData { - address indexer; - address delegator; - } -} diff --git a/packages/contracts/contracts/l2/staking/L2Staking.sol b/packages/contracts/contracts/l2/staking/L2Staking.sol index 278e26a50..305747801 100644 --- a/packages/contracts/contracts/l2/staking/L2Staking.sol +++ b/packages/contracts/contracts/l2/staking/L2Staking.sol @@ -3,16 +3,23 @@ pragma solidity ^0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events + import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; import { Staking } from "../../staking/Staking.sol"; -import { IL2StakingBase } from "./IL2StakingBase.sol"; +import { IL2StakingBase } from "@graphprotocol/interfaces/contracts/contracts/l2/staking/IL2StakingBase.sol"; import { Stakes } from "../../staking/libs/Stakes.sol"; -import { IStakes } from "../../staking/libs/IStakes.sol"; -import { IL2StakingTypes } from "./IL2StakingTypes.sol"; +import { IStakes } from "@graphprotocol/interfaces/contracts/contracts/staking/libs/IStakes.sol"; +import { IL2StakingTypes } from "@graphprotocol/interfaces/contracts/contracts/l2/staking/IL2StakingTypes.sol"; + +// solhint-disable-next-line no-unused-import +import { ICallhookReceiver } from "@graphprotocol/interfaces/contracts/contracts/gateway/ICallhookReceiver.sol"; // Used by @inheritdoc /** * @title L2Staking contract - * @dev This contract is the L2 variant of the Staking contract. It adds a function + * @author Edge & Node + * @notice This contract is the L2 variant of the Staking contract. It adds a function * to receive an indexer's stake or delegation from L1. Note that this contract inherits Staking, * which uses a StakingExtension contract to implement the full IStaking interface through delegatecalls. */ @@ -24,10 +31,14 @@ contract L2Staking is Staking, IL2StakingBase { uint256 private constant MINIMUM_DELEGATION = 1e18; /** - * @dev Emitted when `delegator` delegated `tokens` to the `indexer`, the delegator + * @notice Emitted when `delegator` delegated `tokens` to the `indexer`, the delegator * gets `shares` for the delegation pool proportionally to the tokens staked. * This is copied from IStakingExtension, but we can't inherit from it because we * don't implement the full interface here. + * @param indexer Address of the indexer receiving the delegation + * @param delegator Address of the delegator + * @param tokens Amount of tokens delegated + * @param shares Amount of shares issued to the delegator */ event StakeDelegated(address indexed indexer, address indexed delegator, uint256 tokens, uint256 shares); @@ -48,7 +59,7 @@ contract L2Staking is Staking, IL2StakingBase { } /** - * @notice Receive tokens with a callhook from the bridge. + * @inheritdoc ICallhookReceiver * @dev The encoded _data can contain information about an indexer's stake * or a delegator's delegation. * See L1MessageCodes in IL2Staking for the supported messages. @@ -82,7 +93,7 @@ contract L2Staking is Staking, IL2StakingBase { } /** - * @dev Receive an Indexer's stake from L1. + * @notice Receive an Indexer's stake from L1. * The specified amount is added to the indexer's stake; the indexer's * address is specified in the _indexerData struct. * @param _amount Amount of tokens that were transferred @@ -105,7 +116,7 @@ contract L2Staking is Staking, IL2StakingBase { } /** - * @dev Receive a Delegator's delegation from L1. + * @notice Receive a Delegator's delegation from L1. * The specified amount is added to the delegator's delegation; the delegator's * address and the indexer's address are specified in the _delegationData struct. * Note that no delegation tax is applied here. diff --git a/packages/contracts/contracts/l2/token/GraphTokenUpgradeable.sol b/packages/contracts/contracts/l2/token/GraphTokenUpgradeable.sol index 0f5cf0ecb..d26371533 100644 --- a/packages/contracts/contracts/l2/token/GraphTokenUpgradeable.sol +++ b/packages/contracts/contracts/l2/token/GraphTokenUpgradeable.sol @@ -2,6 +2,10 @@ pragma solidity ^0.7.6; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-increment-by-one, gas-small-strings, gas-strict-inequalities +// solhint-disable named-parameters-mapping + import { ERC20BurnableUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol"; import { ECDSAUpgradeable } from "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol"; @@ -10,7 +14,8 @@ import { Governed } from "../../governance/Governed.sol"; /** * @title GraphTokenUpgradeable contract - * @dev This is the implementation of the ERC20 Graph Token. + * @author Edge & Node + * @notice This is the implementation of the ERC20 Graph Token. * The implementation exposes a permit() function to allow for a spender to send a signed message * and approve funds to a spender following EIP2612 to make integration with other contracts easier. * @@ -47,16 +52,23 @@ abstract contract GraphTokenUpgradeable is GraphUpgradeable, Governed, ERC20Burn bytes32 private DOMAIN_SEPARATOR; // solhint-disable-line var-name-mixedcase /// @dev Addresses for which this mapping is true are allowed to mint tokens mapping(address => bool) private _minters; - /// Nonces for permit signatures for each token holder + /// @notice Nonces for permit signatures for each token holder mapping(address => uint256) public nonces; /// @dev Storage gap added in case we need to add state variables to this contract uint256[47] private __gap; // -- Events -- - /// Emitted when a new minter is added + /** + * @notice Emitted when a new minter is added + * @param account Address of the minter that was added + */ event MinterAdded(address indexed account); - /// Emitted when a minter is removed + + /** + * @notice Emitted when a minter is removed + * @param account Address of the minter that was removed + */ event MinterRemoved(address indexed account); /// @dev Reverts if the caller is not an authorized minter @@ -145,7 +157,7 @@ abstract contract GraphTokenUpgradeable is GraphUpgradeable, Governed, ERC20Burn } /** - * @dev Graph Token Contract initializer. + * @notice Graph Token Contract initializer. * @param _owner Owner of this contract, who will hold the initial supply and will be a minter * @param _initialSupply Initial supply of GRT */ @@ -173,7 +185,7 @@ abstract contract GraphTokenUpgradeable is GraphUpgradeable, Governed, ERC20Burn } /** - * @dev Add a new minter. + * @notice Add a new minter. * @param _account Address of the minter */ function _addMinter(address _account) private { @@ -182,7 +194,7 @@ abstract contract GraphTokenUpgradeable is GraphUpgradeable, Governed, ERC20Burn } /** - * @dev Remove a minter. + * @notice Remove a minter. * @param _account Address of the minter */ function _removeMinter(address _account) private { @@ -191,7 +203,7 @@ abstract contract GraphTokenUpgradeable is GraphUpgradeable, Governed, ERC20Burn } /** - * @dev Get the running network chain ID. + * @notice Get the running network chain ID. * @return The chain ID */ function _getChainID() private pure returns (uint256) { diff --git a/packages/contracts/contracts/l2/token/L2GraphToken.sol b/packages/contracts/contracts/l2/token/L2GraphToken.sol index 639444870..d37731f53 100644 --- a/packages/contracts/contracts/l2/token/L2GraphToken.sol +++ b/packages/contracts/contracts/l2/token/L2GraphToken.sol @@ -2,27 +2,48 @@ pragma solidity ^0.7.6; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events + import { GraphTokenUpgradeable } from "./GraphTokenUpgradeable.sol"; -import { IArbToken } from "../../arbitrum/IArbToken.sol"; +import { IArbToken } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/IArbToken.sol"; /** * @title L2 Graph Token Contract - * @dev Provides the L2 version of the GRT token, meant to be minted/burned + * @author Edge & Node + * @notice Provides the L2 version of the GRT token, meant to be minted/burned * through the L2GraphTokenGateway. */ contract L2GraphToken is GraphTokenUpgradeable, IArbToken { - /// Address of the gateway (on L2) that is allowed to mint tokens + /// @notice Address of the gateway (on L2) that is allowed to mint tokens address public gateway; - /// Address of the corresponding Graph Token contract on L1 + /// @notice Address of the corresponding Graph Token contract on L1 address public override l1Address; - /// Emitted when the bridge / gateway has minted new tokens, i.e. tokens were transferred to L2 + /** + * @notice Emitted when the bridge / gateway has minted new tokens, i.e. tokens were transferred to L2 + * @param account Address that received the minted tokens + * @param amount Amount of tokens minted + */ event BridgeMinted(address indexed account, uint256 amount); - /// Emitted when the bridge / gateway has burned tokens, i.e. tokens were transferred back to L1 + + /** + * @notice Emitted when the bridge / gateway has burned tokens, i.e. tokens were transferred back to L1 + * @param account Address from which tokens were burned + * @param amount Amount of tokens burned + */ event BridgeBurned(address indexed account, uint256 amount); - /// Emitted when the address of the gateway has been updated + + /** + * @notice Emitted when the address of the gateway has been updated + * @param gateway Address of the new gateway + */ event GatewaySet(address gateway); - /// Emitted when the address of the Graph Token contract on L1 has been updated + + /** + * @notice Emitted when the address of the Graph Token contract on L1 has been updated + * @param l1Address Address of the L1 Graph Token contract + */ event L1AddressSet(address l1Address); /** @@ -69,9 +90,8 @@ contract L2GraphToken is GraphTokenUpgradeable, IArbToken { } /** - * @notice Increases token supply, only callable by the L1/L2 bridge (when tokens are transferred to L2) - * @param _account Address to credit with the new tokens - * @param _amount Number of tokens to mint + * @inheritdoc IArbToken + * @dev Only callable by the L2GraphTokenGateway when tokens are transferred to L2 */ function bridgeMint(address _account, uint256 _amount) external override onlyGateway { _mint(_account, _amount); @@ -79,9 +99,8 @@ contract L2GraphToken is GraphTokenUpgradeable, IArbToken { } /** - * @notice Decreases token supply, only callable by the L1/L2 bridge (when tokens are transferred to L1). - * @param _account Address from which to extract the tokens - * @param _amount Number of tokens to burn + * @inheritdoc IArbToken + * @dev Only callable by the L2GraphTokenGateway when tokens are transferred back to L1 */ function bridgeBurn(address _account, uint256 _amount) external override onlyGateway { burnFrom(_account, _amount); diff --git a/packages/contracts/contracts/libraries/Base58Encoder.sol b/packages/contracts/contracts/libraries/Base58Encoder.sol index 9af197855..91caa8855 100644 --- a/packages/contracts/contracts/libraries/Base58Encoder.sol +++ b/packages/contracts/contracts/libraries/Base58Encoder.sol @@ -2,14 +2,25 @@ pragma solidity ^0.7.6; -/// @title Base58Encoder -/// @author Original author - Martin Lundfall (martin.lundfall@gmail.com) -/// Based on https://github.com/MrChico/verifyIPFS +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-increment-by-one + +/** + * @title Base58Encoder + * @author Original author - Martin Lundfall (martin.lundfall@gmail.com) + * @notice Library for encoding bytes to Base58 format, used for IPFS hashes + * @dev Based on https://github.com/MrChico/verifyIPFS + */ library Base58Encoder { - bytes constant sha256MultiHash = hex"1220"; - bytes constant ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + /// @dev SHA-256 multihash prefix for IPFS hashes + // solhint-disable-next-line const-name-snakecase + bytes internal constant sha256MultiHash = hex"1220"; + /// @dev Base58 alphabet used for encoding + bytes internal constant ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; - /// @dev Converts hex string to base 58 + /// @notice Converts hex string to base 58 + /// @param source The bytes to encode + /// @return The base58 encoded bytes function encode(bytes memory source) internal pure returns (bytes memory) { if (source.length == 0) return new bytes(0); uint8[] memory digits = new uint8[](64); @@ -32,6 +43,12 @@ library Base58Encoder { return toAlphabet(reverse(truncate(digits, digitlength))); } + /** + * @notice Truncate an array to a specific length + * @param array The array to truncate + * @param length The desired length + * @return The truncated array + */ function truncate(uint8[] memory array, uint8 length) internal pure returns (uint8[] memory) { uint8[] memory output = new uint8[](length); for (uint256 i = 0; i < length; i++) { @@ -40,6 +57,11 @@ library Base58Encoder { return output; } + /** + * @notice Reverse an array + * @param input The array to reverse + * @return The reversed array + */ function reverse(uint8[] memory input) internal pure returns (uint8[] memory) { uint8[] memory output = new uint8[](input.length); for (uint256 i = 0; i < input.length; i++) { @@ -48,6 +70,11 @@ library Base58Encoder { return output; } + /** + * @notice Convert indices to alphabet characters + * @param indices The indices to convert + * @return The alphabet characters as bytes + */ function toAlphabet(uint8[] memory indices) internal pure returns (bytes memory) { bytes memory output = new bytes(indices.length); for (uint256 i = 0; i < indices.length; i++) { diff --git a/packages/contracts/contracts/libraries/HexStrings.sol b/packages/contracts/contracts/libraries/HexStrings.sol index 4842883a9..2b5e314e6 100644 --- a/packages/contracts/contracts/libraries/HexStrings.sol +++ b/packages/contracts/contracts/libraries/HexStrings.sol @@ -2,12 +2,22 @@ pragma solidity ^0.7.6; -/// @title HexStrings -/// Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8dd744fc1843d285c38e54e9d439dea7f6b93495/contracts/utils/Strings.sol +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-increment-by-one + +/** + * @title HexStrings + * @author Edge & Node + * @notice Library for converting values to hexadecimal string representations + * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8dd744fc1843d285c38e54e9d439dea7f6b93495/contracts/utils/Strings.sol + */ library HexStrings { + /// @dev Hexadecimal symbols used for string conversion bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - /// @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. + /// @notice Converts a `uint256` to its ASCII `string` hexadecimal representation. + /// @param value The uint256 value to convert + /// @return The hexadecimal string representation function toString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; @@ -21,7 +31,10 @@ library HexStrings { return toHexString(value, length); } - /// @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. + /// @notice Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. + /// @param value The uint256 value to convert + /// @param length The fixed length of the output string + /// @return The hexadecimal string representation with fixed length function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; diff --git a/packages/contracts/contracts/payments/AllocationExchange.sol b/packages/contracts/contracts/payments/AllocationExchange.sol index 5f0b30b44..288bdda32 100644 --- a/packages/contracts/contracts/payments/AllocationExchange.sol +++ b/packages/contracts/contracts/payments/AllocationExchange.sol @@ -3,16 +3,20 @@ pragma solidity ^0.7.6; pragma abicoder v2; -import "@openzeppelin/contracts/cryptography/ECDSA.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-calldata-parameters, gas-increment-by-one, gas-indexed-events, gas-small-strings +// solhint-disable named-parameters-mapping -import "../governance/Governed.sol"; -import "../staking/IStaking.sol"; -import { IGraphToken } from "../token/IGraphToken.sol"; +import { ECDSA } from "@openzeppelin/contracts/cryptography/ECDSA.sol"; +import { Address } from "@openzeppelin/contracts/utils/Address.sol"; +import { Governed } from "../governance/Governed.sol"; +import { IStaking } from "@graphprotocol/interfaces/contracts/contracts/staking/IStaking.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; /** * @title Allocation Exchange - * @dev This contract holds tokens that anyone with a voucher signed by the + * @author Edge & Node + * @notice This contract holds tokens that anyone with a voucher signed by the * authority can redeem. The contract validates if the voucher presented is valid * and then sends tokens to the Staking contract by calling the collect() function * passing the voucher allocationID. The contract enforces that only one voucher for @@ -20,9 +24,14 @@ import { IGraphToken } from "../token/IGraphToken.sol"; * Only governance can change the authority. */ contract AllocationExchange is Governed { - // An allocation voucher represents a signed message that allows - // redeeming an amount of funds from this contract and collect - // them as part of an allocation + /** + * @dev An allocation voucher represents a signed message that allows + * redeeming an amount of funds from this contract and collect + * them as part of an allocation + * @param allocationID Address of the allocation + * @param amount Amount of tokens to redeem + * @param signature Signature from the authority (65 bytes) + */ struct AllocationVoucher { address allocationID; uint256 amount; @@ -31,20 +40,43 @@ contract AllocationExchange is Governed { // -- Constants -- + /// @dev Maximum uint256 value used for unlimited token approvals uint256 private constant MAX_UINT256 = 2 ** 256 - 1; + /// @dev Expected length of ECDSA signatures uint256 private constant SIGNATURE_LENGTH = 65; // -- State -- - IStaking private immutable staking; - IGraphToken private immutable graphToken; + /// @dev Reference to the Staking contract + IStaking private immutable STAKING; + /// @dev Reference to the Graph Token contract + IGraphToken private immutable GRAPH_TOKEN; + /// @notice Mapping of authorized accounts that can redeem allocations mapping(address => bool) public authority; + /// @notice Mapping of allocations that have been redeemed mapping(address => bool) public allocationsRedeemed; // -- Events + /** + * @notice Emitted when an authority is set or unset + * @param account Address of the authority + * @param authorized Whether the authority is authorized + */ event AuthoritySet(address indexed account, bool authorized); + + /** + * @notice Emitted when an allocation voucher is redeemed + * @param allocationID Address of the allocation + * @param amount Amount of tokens redeemed + */ event AllocationRedeemed(address indexed allocationID, uint256 amount); + + /** + * @notice Emitted when tokens are withdrawn from the contract + * @param to Address that received the tokens + * @param amount Amount of tokens withdrawn + */ event TokensWithdrawn(address indexed to, uint256 amount); // -- Functions @@ -60,8 +92,8 @@ contract AllocationExchange is Governed { require(_governor != address(0), "Exchange: governor must be set"); Governed._initialize(_governor); - graphToken = _graphToken; - staking = _staking; + GRAPH_TOKEN = _graphToken; + STAKING = _staking; _setAuthority(_authority, true); } @@ -70,7 +102,7 @@ contract AllocationExchange is Governed { * @dev Increased gas efficiency instead of approving on each voucher redeem */ function approveAll() external { - graphToken.approve(address(staking), MAX_UINT256); + GRAPH_TOKEN.approve(address(STAKING), MAX_UINT256); } /** @@ -82,7 +114,7 @@ contract AllocationExchange is Governed { function withdraw(address _to, uint256 _amount) external onlyGovernor { require(_to != address(0), "Exchange: empty destination"); require(_amount != 0, "Exchange: empty amount"); - require(graphToken.transfer(_to, _amount), "Exchange: cannot transfer"); + require(GRAPH_TOKEN.transfer(_to, _amount), "Exchange: cannot transfer"); emit TokensWithdrawn(_to, _amount); } @@ -155,7 +187,7 @@ contract AllocationExchange is Governed { // Make the staking contract collect funds from this contract // The Staking contract will validate if the allocation is valid - staking.collect(_voucher.amount, _voucher.allocationID); + STAKING.collect(_voucher.amount, _voucher.allocationID); emit AllocationRedeemed(_voucher.allocationID, _voucher.amount); } diff --git a/packages/contracts/contracts/rewards/IRewardsIssuer.sol b/packages/contracts/contracts/rewards/IRewardsIssuer.sol deleted file mode 100644 index d50410b33..000000000 --- a/packages/contracts/contracts/rewards/IRewardsIssuer.sol +++ /dev/null @@ -1,37 +0,0 @@ -// 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); -} diff --git a/packages/contracts/contracts/rewards/IRewardsManager.sol b/packages/contracts/contracts/rewards/IRewardsManager.sol deleted file mode 100644 index b31064d1b..000000000 --- a/packages/contracts/contracts/rewards/IRewardsManager.sol +++ /dev/null @@ -1,57 +0,0 @@ -// 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); -} diff --git a/packages/contracts/contracts/rewards/RewardsManager.sol b/packages/contracts/contracts/rewards/RewardsManager.sol index 58f654b91..767449026 100644 --- a/packages/contracts/contracts/rewards/RewardsManager.sol +++ b/packages/contracts/contracts/rewards/RewardsManager.sol @@ -3,19 +3,24 @@ pragma solidity 0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-increment-by-one, gas-indexed-events, gas-small-strings, gas-strict-inequalities + 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 { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { RewardsManagerV5Storage } from "./RewardsManagerStorage.sol"; -import { IRewardsManager } from "./IRewardsManager.sol"; -import { IRewardsIssuer } from "./IRewardsIssuer.sol"; +import { IRewardsIssuer } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsIssuer.sol"; +import { IRewardsManager } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsManager.sol"; /** * @title Rewards Manager Contract + * @author Edge & Node + * @notice Manages rewards distribution for indexers and delegators in the Graph Protocol * @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 @@ -30,6 +35,7 @@ import { IRewardsIssuer } from "./IRewardsIssuer.sol"; * - getRewards * These functions may overestimate the actual rewards due to changes in the total supply * until the actual takeRewards function is called. + * custom:security-contact Please email security+contracts@ thegraph.com (remove space) if you find any bugs. We might have an active bug bounty program. */ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsManager { using SafeMath for uint256; @@ -40,27 +46,32 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa // -- Events -- /** - * @dev Emitted when rewards are assigned to an indexer. + * @notice 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 + * @param indexer Address of the indexer receiving rewards + * @param allocationID Address of the allocation receiving rewards + * @param amount Amount of rewards assigned */ event HorizonRewardsAssigned(address indexed indexer, address indexed allocationID, uint256 amount); /** - * @dev Emitted when rewards are denied to an indexer + * @notice 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 + * @notice 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 + * @notice Emitted when the subgraph service is set + * @param oldSubgraphService Previous subgraph service address + * @param newSubgraphService New subgraph service address */ event SubgraphServiceSet(address indexed oldSubgraphService, address indexed newSubgraphService); @@ -85,20 +96,20 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa // -- Config -- /** - * @dev Sets the GRT issuance per block. - * The issuance is defined as a fixed amount of rewards per block in GRT. + * @inheritdoc IRewardsManager + * + * @dev 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. + * @notice Sets the GRT issuance per block. + * @dev 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 { @@ -110,8 +121,7 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa } /** - * @notice Sets the subgraph oracle allowed to deny distribution of rewards to subgraphs - * @param _subgraphAvailabilityOracle Address of the subgraph availability oracle + * @inheritdoc IRewardsManager */ function setSubgraphAvailabilityOracle(address _subgraphAvailabilityOracle) external override onlyGovernor { subgraphAvailabilityOracle = _subgraphAvailabilityOracle; @@ -119,7 +129,7 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa } /** - * @notice Sets the minimum signaled tokens on a subgraph to start accruing rewards + * @inheritdoc IRewardsManager * @dev Can be set to zero which means that this feature is not being used * @param _minimumSubgraphSignal Minimum signaled tokens */ @@ -133,6 +143,9 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa emit ParameterUpdated("minimumSubgraphSignal"); } + /** + * @inheritdoc IRewardsManager + */ function setSubgraphService(address _subgraphService) external override onlyGovernor { address oldSubgraphService = address(subgraphService); subgraphService = IRewardsIssuer(_subgraphService); @@ -142,17 +155,15 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa // -- Denylist -- /** - * @notice Denies to claim rewards for a subgraph + * @inheritdoc IRewardsManager * @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. + * @notice 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 */ @@ -162,11 +173,7 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa 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 - */ + /// @inheritdoc IRewardsManager function isDenied(bytes32 _subgraphDeploymentID) public view override returns (bool) { return denylist[_subgraphDeploymentID] > 0; } @@ -174,7 +181,7 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa // -- Getters -- /** - * @notice Gets the issuance of rewards per signal since last updated + * @inheritdoc IRewardsManager * @dev Linear formula: `x = r * t` * * Notation: @@ -209,19 +216,12 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa return x.mul(FIXED_POINT_SCALING_FACTOR).div(signalledTokens); } - /** - * @notice Gets the currently accumulated rewards per signal - * @return Currently accumulated rewards per signal - */ + /// @inheritdoc IRewardsManager 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 - */ + /// @inheritdoc IRewardsManager function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID) public view override returns (uint256) { Subgraph storage subgraph = subgraphs[_subgraphDeploymentID]; @@ -237,12 +237,7 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa 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 - */ + /// @inheritdoc IRewardsManager function getAccRewardsPerAllocatedToken( bytes32 _subgraphDeploymentID ) public view override returns (uint256, uint256) { @@ -280,10 +275,9 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa // -- Updates -- /** - * @notice Updates the accumulated rewards per signal and save checkpoint block number + * @inheritdoc IRewardsManager * @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(); @@ -292,11 +286,9 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa } /** - * @notice Triggers an update of rewards for a subgraph + * @inheritdoc IRewardsManager * @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 @@ -310,12 +302,8 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa } /** - * @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 + * @inheritdoc IRewardsManager + * @dev Hook called from the Staking contract on allocate() and close() */ function onSubgraphAllocationUpdate(bytes32 _subgraphDeploymentID) public override returns (uint256) { Subgraph storage subgraph = subgraphs[_subgraphDeploymentID]; @@ -327,13 +315,7 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa 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 - */ + /// @inheritdoc IRewardsManager function getRewards(address _rewardsIssuer, address _allocationID) external view override returns (uint256) { require( _rewardsIssuer == address(staking()) || _rewardsIssuer == address(subgraphService), @@ -359,7 +341,7 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa } /** - * @dev Calculate rewards for a given accumulated rewards per allocated token. + * @notice Calculate rewards for a given accumulated rewards per allocated token * @param _tokens Tokens allocated * @param _accRewardsPerAllocatedToken Allocation accumulated rewards per token * @return Rewards amount @@ -372,7 +354,7 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa } /** - * @dev Calculate current rewards for a given allocation. + * @notice Calculate current rewards for a given allocation. * @param _tokens Tokens allocated * @param _startAccRewardsPerAllocatedToken Allocation start accumulated rewards * @param _endAccRewardsPerAllocatedToken Allocation end accumulated rewards @@ -388,13 +370,10 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa } /** - * @dev Pull rewards from the contract for a particular allocation. - * This function can only be called by an authorized rewards issuer which are + * @inheritdoc IRewardsManager + * @dev 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; diff --git a/packages/contracts/contracts/rewards/RewardsManagerStorage.sol b/packages/contracts/contracts/rewards/RewardsManagerStorage.sol index d2ffa2b42..d78eb81ef 100644 --- a/packages/contracts/contracts/rewards/RewardsManagerStorage.sol +++ b/packages/contracts/contracts/rewards/RewardsManagerStorage.sol @@ -1,44 +1,78 @@ // SPDX-License-Identifier: GPL-2.0-or-later +/* solhint-disable one-contract-per-file */ + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable named-parameters-mapping + pragma solidity ^0.7.6 || 0.8.27; -import { IRewardsIssuer } from "./IRewardsIssuer.sol"; -import { IRewardsManager } from "./IRewardsManager.sol"; +import { IRewardsIssuer } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsIssuer.sol"; +import { IRewardsManager } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsManager.sol"; import { Managed } from "../governance/Managed.sol"; +/** + * @title RewardsManagerV1Storage + * @author Edge & Node + * @notice Storage layout for RewardsManager V1 + */ contract RewardsManagerV1Storage is Managed { // -- State -- + /// @dev Deprecated issuance rate variable (no longer used) uint256 private __DEPRECATED_issuanceRate; // solhint-disable-line var-name-mixedcase + /// @notice Accumulated rewards per signal uint256 public accRewardsPerSignal; + /// @notice Block number when accumulated rewards per signal was last updated uint256 public accRewardsPerSignalLastBlockUpdated; - // Address of role allowed to deny rewards on subgraphs + /// @notice Address of role allowed to deny rewards on subgraphs address public subgraphAvailabilityOracle; - // Subgraph related rewards: subgraph deployment ID => subgraph rewards + /// @notice 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) + /// @notice Subgraph denylist: subgraph deployment ID => block when added or zero (if not denied) mapping(bytes32 => uint256) public denylist; } +/** + * @title RewardsManagerV2Storage + * @author Edge & Node + * @notice Storage layout for RewardsManager V2 + */ contract RewardsManagerV2Storage is RewardsManagerV1Storage { - // Minimum amount of signaled tokens on a subgraph required to accrue rewards + /// @notice Minimum amount of signaled tokens on a subgraph required to accrue rewards uint256 public minimumSubgraphSignal; } +/** + * @title RewardsManagerV3Storage + * @author Edge & Node + * @notice Storage layout for RewardsManager V3 + */ contract RewardsManagerV3Storage is RewardsManagerV2Storage { - // Snapshot of the total supply of GRT when accRewardsPerSignal was last updated + /// @dev Deprecated token supply snapshot variable (no longer used) uint256 private __DEPRECATED_tokenSupplySnapshot; // solhint-disable-line var-name-mixedcase } +/** + * @title RewardsManagerV4Storage + * @author Edge & Node + * @notice Storage layout for RewardsManager V4 + */ contract RewardsManagerV4Storage is RewardsManagerV3Storage { - // GRT issued for indexer rewards per block + /// @notice GRT issued for indexer rewards per block + /// @dev Only used when issuanceAllocator is zero address. uint256 public issuancePerBlock; } +/** + * @title RewardsManagerV5Storage + * @author Edge & Node + * @notice Storage layout for RewardsManager V5 + */ contract RewardsManagerV5Storage is RewardsManagerV4Storage { - // Address of the subgraph service + /// @notice Address of the subgraph service IRewardsIssuer public subgraphService; } diff --git a/packages/contracts/contracts/rewards/SubgraphAvailabilityManager.sol b/packages/contracts/contracts/rewards/SubgraphAvailabilityManager.sol index 3c0c98cd2..d24577b42 100644 --- a/packages/contracts/contracts/rewards/SubgraphAvailabilityManager.sol +++ b/packages/contracts/contracts/rewards/SubgraphAvailabilityManager.sol @@ -2,12 +2,17 @@ pragma solidity ^0.7.6; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-increment-by-one, gas-indexed-events, gas-small-strings, gas-strict-inequalities +// solhint-disable named-parameters-mapping + import { Governed } from "../governance/Governed.sol"; -import { IRewardsManager } from "./IRewardsManager.sol"; +import { IRewardsManager } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsManager.sol"; /** * @title Subgraph Availability Manager - * @dev Manages the availability of subgraphs by allowing oracles to vote on whether + * @author Edge & Node + * @notice Manages the availability of subgraphs by allowing oracles to vote on whether * a subgraph should be denied rewards or not. When enough oracles have voted to deny or * allow rewards for a subgraph, it calls the RewardsManager Contract to set the correct * state. The oracles and the execution threshold are set at deployment time. @@ -21,15 +26,16 @@ contract SubgraphAvailabilityManager is Governed { uint256 public constant NUM_ORACLES = 5; /// @notice Number of votes required to execute a deny or allow call to the RewardsManager - uint256 public immutable executionThreshold; + uint256 public immutable executionThreshold; // solhint-disable-line immutable-vars-naming /// @dev Address of the RewardsManager contract + // solhint-disable-next-line immutable-vars-naming IRewardsManager private immutable rewardsManager; // -- State -- - /// @dev Nonce for generating votes on subgraph deployment IDs. - /// Increased whenever oracles or voteTimeLimit change, to invalidate old votes. + /// @notice Nonce for generating votes on subgraph deployment IDs + /// @dev Increased whenever oracles or voteTimeLimit change, to invalidate old votes uint256 public currentNonce; /// @notice Time limit for a vote to be valid @@ -39,30 +45,30 @@ contract SubgraphAvailabilityManager is Governed { address[NUM_ORACLES] public oracles; /// @notice Mapping of current nonce to subgraph deployment ID to an array of timestamps of last deny vote - /// currentNonce => subgraphDeploymentId => timestamp[oracleIndex] + /// @dev currentNonce => subgraphDeploymentId => timestamp[oracleIndex] mapping(uint256 => mapping(bytes32 => uint256[NUM_ORACLES])) public lastDenyVote; - /// @notice Mapping of current nonce to subgraph deployment ID to an array of timestamp of last allow vote - /// currentNonce => subgraphDeploymentId => timestamp[oracleIndex] + /// @notice Mapping of current nonce to subgraph deployment ID to an array of timestamp of last allow vote + /// @dev currentNonce => subgraphDeploymentId => timestamp[oracleIndex] mapping(uint256 => mapping(bytes32 => uint256[NUM_ORACLES])) public lastAllowVote; // -- Events -- /** - * @dev Emitted when an oracle is set + * @notice Emitted when an oracle is set * @param index Index of the oracle * @param oracle Address of the oracle */ event OracleSet(uint256 indexed index, address indexed oracle); /** - * @dev Emitted when the vote time limit is set + * @notice Emitted when the vote time limit is set * @param voteTimeLimit Vote time limit in seconds */ event VoteTimeLimitSet(uint256 voteTimeLimit); /** - * @dev Emitted when an oracle votes to deny or allow a subgraph + * @notice Emitted when an oracle votes to deny or allow a subgraph * @param subgraphDeploymentID Subgraph deployment ID * @param deny True to deny, false to allow * @param oracleIndex Index of the oracle voting @@ -72,6 +78,10 @@ contract SubgraphAvailabilityManager is Governed { // -- Modifiers -- + /** + * @dev Modifier to restrict access to authorized oracles only + * @param _oracleIndex Index of the oracle in the oracles array + */ modifier onlyOracle(uint256 _oracleIndex) { require(_oracleIndex < NUM_ORACLES, "SAM: index out of bounds"); require(msg.sender == oracles[_oracleIndex], "SAM: caller must be oracle"); @@ -81,7 +91,7 @@ contract SubgraphAvailabilityManager is Governed { // -- Constructor -- /** - * @dev Contract constructor + * @notice Contract constructor * @param _governor Account that can set or remove oracles and set the vote time limit * @param _rewardsManager Address of the RewardsManager contract * @param _executionThreshold Number of votes required to execute a deny or allow call to the RewardsManager @@ -118,7 +128,7 @@ contract SubgraphAvailabilityManager is Governed { // -- Functions -- /** - * @dev Set the vote time limit. Refreshes all existing votes by incrementing the current nonce. + * @notice Set the vote time limit. Refreshes all existing votes by incrementing the current nonce. * @param _voteTimeLimit Vote time limit in seconds */ function setVoteTimeLimit(uint256 _voteTimeLimit) external onlyGovernor { @@ -128,7 +138,7 @@ contract SubgraphAvailabilityManager is Governed { } /** - * @dev Set oracle address with index. Refreshes all existing votes by incrementing the current nonce. + * @notice Set oracle address with index. Refreshes all existing votes by incrementing the current nonce. * @param _index Index of the oracle * @param _oracle Address of the oracle */ @@ -144,7 +154,7 @@ contract SubgraphAvailabilityManager is Governed { } /** - * @dev Vote deny or allow for a subgraph. + * @notice Vote deny or allow for a subgraph. * NOTE: Can only be called by an oracle. * @param _subgraphDeploymentID Subgraph deployment ID * @param _deny True to deny, false to allow @@ -155,7 +165,7 @@ contract SubgraphAvailabilityManager is Governed { } /** - * @dev Vote deny or allow for many subgraphs. + * @notice Vote deny or allow for many subgraphs. * NOTE: Can only be called by an oracle. * @param _subgraphDeploymentID Array of subgraph deployment IDs * @param _deny Array of booleans, true to deny, false to allow @@ -173,7 +183,7 @@ contract SubgraphAvailabilityManager is Governed { } /** - * @dev Vote deny or allow for a subgraph. + * @notice Vote deny or allow for a subgraph. * When oracles cast their votes we store the timestamp of the vote. * Check if the execution threshold has been reached for a subgraph. * If execution threshold is reached we call the RewardsManager to set the correct state. @@ -203,7 +213,7 @@ contract SubgraphAvailabilityManager is Governed { } /** - * @dev Check if the execution threshold has been reached for a subgraph. + * @notice Check if the execution threshold has been reached for a subgraph. * For a vote to be valid it needs to be within the vote time limit. * @param _subgraphDeploymentID Subgraph deployment ID * @param _deny True to deny, false to allow diff --git a/packages/contracts/contracts/staking/IL1GraphTokenLockTransferTool.sol b/packages/contracts/contracts/staking/IL1GraphTokenLockTransferTool.sol deleted file mode 100644 index b935682b9..000000000 --- a/packages/contracts/contracts/staking/IL1GraphTokenLockTransferTool.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity >=0.6.12 <0.8.0; -pragma abicoder v2; - -/** - * @title Interface for the L1GraphTokenLockTransferTool contract - * @dev This interface defines the function to get the L2 wallet address for a given L1 token lock wallet. - * The Transfer Tool contract is implemented in the token-distribution repo: https://github.com/graphprotocol/token-distribution/pull/64 - * and is only included here to provide support in L1Staking for the transfer of stake and delegation - * owned by token lock contracts. See GIP-0046 for details: https://forum.thegraph.com/t/4023 - */ -interface IL1GraphTokenLockTransferTool { - /** - * @notice Pulls ETH from an L1 wallet's account to use for L2 ticket gas. - * @dev This function is only callable by the staking contract. - * @param _l1Wallet Address of the L1 token lock wallet - * @param _amount Amount of ETH to pull from the transfer tool contract - */ - function pullETH(address _l1Wallet, uint256 _amount) external; - - /** - * @notice Get the L2 token lock wallet address for a given L1 token lock wallet - * @dev In the actual L1GraphTokenLockTransferTool contract, this is simply the default getter for a public mapping variable. - * @param _l1Wallet Address of the L1 token lock wallet - * @return Address of the L2 token lock wallet if the wallet has an L2 counterpart, or address zero if - * the wallet doesn't have an L2 counterpart (or is not known to be a token lock wallet). - */ - function l2WalletAddress(address _l1Wallet) external view returns (address); -} diff --git a/packages/contracts/contracts/staking/IL1Staking.sol b/packages/contracts/contracts/staking/IL1Staking.sol deleted file mode 100644 index 4a446f787..000000000 --- a/packages/contracts/contracts/staking/IL1Staking.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity >=0.6.12 <0.8.0; -pragma abicoder v2; - -import { IStaking } from "./IStaking.sol"; -import { IL1StakingBase } from "./IL1StakingBase.sol"; - -/** - * @title Interface for the L1 Staking contract - * @notice This is the interface that should be used when interacting with the L1 Staking contract. - * It extends the IStaking interface with the functions that are specific to L1, adding the transfer tools - * to send stake and delegation to L2. - * @dev Note that L1Staking 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 IL1Staking is IStaking, IL1StakingBase {} diff --git a/packages/contracts/contracts/staking/IL1StakingBase.sol b/packages/contracts/contracts/staking/IL1StakingBase.sol deleted file mode 100644 index fad2136c2..000000000 --- a/packages/contracts/contracts/staking/IL1StakingBase.sol +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity >=0.6.12 <0.8.0; -pragma abicoder v2; - -import { IL1GraphTokenLockTransferTool } from "./IL1GraphTokenLockTransferTool.sol"; - -/** - * @title Base interface for the L1Staking contract. - * @notice This interface is used to define the transfer tools that are implemented in L1Staking. - * @dev Note it includes only the L1-specific functionality, not the full IStaking interface. - */ -interface IL1StakingBase { - /// @dev Emitted when an indexer transfers their stake to L2. - /// This can happen several times as indexers can transfer partial stake. - event IndexerStakeTransferredToL2( - address indexed indexer, - address indexed l2Indexer, - uint256 transferredStakeTokens - ); - - /// @dev Emitted when a delegator transfers their delegation to L2 - event DelegationTransferredToL2( - address indexed delegator, - address indexed l2Delegator, - address indexed indexer, - address l2Indexer, - uint256 transferredDelegationTokens - ); - - /// @dev Emitted when the L1GraphTokenLockTransferTool is set - event L1GraphTokenLockTransferToolSet(address l1GraphTokenLockTransferTool); - - /// @dev Emitted when a delegator unlocks their tokens ahead of time because the indexer has transferred to L2 - event StakeDelegatedUnlockedDueToL2Transfer(address indexed indexer, address indexed delegator); - - /** - * @notice Set the L1GraphTokenLockTransferTool contract address - * @dev This function can only be called by the governor. - * @param _l1GraphTokenLockTransferTool Address of the L1GraphTokenLockTransferTool contract - */ - function setL1GraphTokenLockTransferTool(IL1GraphTokenLockTransferTool _l1GraphTokenLockTransferTool) external; - - /** - * @notice Send an indexer's stake to L2. - * @dev This function can only be called by the indexer (not an operator). - * It will validate that the remaining stake is sufficient to cover all the allocated - * stake, so the indexer might have to close some allocations before transferring. - * It will also check that the indexer's stake is not locked for withdrawal. - * Since the indexer address might be an L1-only contract, the function takes a beneficiary - * address that will be the indexer's address in L2. - * The caller must provide an amount of ETH to use for the L2 retryable ticket, that - * must be at least `_maxSubmissionCost + _gasPriceBid * _maxGas`. - * @param _l2Beneficiary Address of the indexer in L2. If the indexer has previously transferred stake, this must match the previously-used value. - * @param _amount Amount of stake GRT to transfer to L2 - * @param _maxGas Max gas to use for the L2 retryable ticket - * @param _gasPriceBid Gas price bid for the L2 retryable ticket - * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket - */ - function transferStakeToL2( - address _l2Beneficiary, - uint256 _amount, - uint256 _maxGas, - uint256 _gasPriceBid, - uint256 _maxSubmissionCost - ) external payable; - - /** - * @notice Send an indexer's stake to L2, from a GraphTokenLockWallet vesting contract. - * @dev This function can only be called by the indexer (not an operator). - * It will validate that the remaining stake is sufficient to cover all the allocated - * stake, so the indexer might have to close some allocations before transferring. - * It will also check that the indexer's stake is not locked for withdrawal. - * The L2 beneficiary for the stake will be determined by calling the L1GraphTokenLockTransferTool contract, - * so the caller must have previously transferred tokens through that first - * (see GIP-0046 for details: https://forum.thegraph.com/t/4023). - * The ETH for the L2 gas will be pulled from the L1GraphTokenLockTransferTool, so the owner of - * the GraphTokenLockWallet must have previously deposited at least `_maxSubmissionCost + _gasPriceBid * _maxGas` - * ETH into the L1GraphTokenLockTransferTool contract (using its depositETH function). - * @param _amount Amount of stake GRT to transfer to L2 - * @param _maxGas Max gas to use for the L2 retryable ticket - * @param _gasPriceBid Gas price bid for the L2 retryable ticket - * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket - */ - function transferLockedStakeToL2( - uint256 _amount, - uint256 _maxGas, - uint256 _gasPriceBid, - uint256 _maxSubmissionCost - ) external; - - /** - * @notice Send a delegator's delegated tokens to L2 - * @dev This function can only be called by the delegator. - * This function will validate that the indexer has transferred their stake using transferStakeToL2, - * and that the delegation is not locked for undelegation. - * Since the delegator's address might be an L1-only contract, the function takes a beneficiary - * address that will be the delegator's address in L2. - * The caller must provide an amount of ETH to use for the L2 retryable ticket, that - * must be at least `_maxSubmissionCost + _gasPriceBid * _maxGas`. - * @param _indexer Address of the indexer (in L1, before transferring to L2) - * @param _l2Beneficiary Address of the delegator in L2 - * @param _maxGas Max gas to use for the L2 retryable ticket - * @param _gasPriceBid Gas price bid for the L2 retryable ticket - * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket - */ - function transferDelegationToL2( - address _indexer, - address _l2Beneficiary, - uint256 _maxGas, - uint256 _gasPriceBid, - uint256 _maxSubmissionCost - ) external payable; - - /** - * @notice Send a delegator's delegated tokens to L2, for a GraphTokenLockWallet vesting contract - * @dev This function can only be called by the delegator. - * This function will validate that the indexer has transferred their stake using transferStakeToL2, - * and that the delegation is not locked for undelegation. - * The L2 beneficiary for the delegation will be determined by calling the L1GraphTokenLockTransferTool contract, - * so the caller must have previously transferred tokens through that first - * (see GIP-0046 for details: https://forum.thegraph.com/t/4023). - * The ETH for the L2 gas will be pulled from the L1GraphTokenLockTransferTool, so the owner of - * the GraphTokenLockWallet must have previously deposited at least `_maxSubmissionCost + _gasPriceBid * _maxGas` - * ETH into the L1GraphTokenLockTransferTool contract (using its depositETH function). - * @param _indexer Address of the indexer (in L1, before transferring to L2) - * @param _maxGas Max gas to use for the L2 retryable ticket - * @param _gasPriceBid Gas price bid for the L2 retryable ticket - * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket - */ - function transferLockedDelegationToL2( - address _indexer, - uint256 _maxGas, - uint256 _gasPriceBid, - uint256 _maxSubmissionCost - ) external; - - /** - * @notice Unlock a delegator's delegated tokens, if the indexer has transferred to L2 - * @dev This function can only be called by the delegator. - * This function will validate that the indexer has transferred their stake using transferStakeToL2, - * and that the indexer has no remaining stake in L1. - * The tokens must previously be locked for undelegation by calling `undelegate()`, - * and can be withdrawn with `withdrawDelegated()` immediately after calling this. - * @param _indexer Address of the indexer (in L1, before transferring to L2) - */ - function unlockDelegationToTransferredIndexer(address _indexer) external; -} diff --git a/packages/contracts/contracts/staking/IStaking.sol b/packages/contracts/contracts/staking/IStaking.sol deleted file mode 100644 index a7d89feea..000000000 --- a/packages/contracts/contracts/staking/IStaking.sol +++ /dev/null @@ -1,18 +0,0 @@ -// 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 {} diff --git a/packages/contracts/contracts/staking/IStakingBase.sol b/packages/contracts/contracts/staking/IStakingBase.sol deleted file mode 100644 index 588144b2a..000000000 --- a/packages/contracts/contracts/staking/IStakingBase.sol +++ /dev/null @@ -1,400 +0,0 @@ -// 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); -} diff --git a/packages/contracts/contracts/staking/IStakingData.sol b/packages/contracts/contracts/staking/IStakingData.sol deleted file mode 100644 index 149e3b8a6..000000000 --- a/packages/contracts/contracts/staking/IStakingData.sol +++ /dev/null @@ -1,59 +0,0 @@ -// 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; - } -} diff --git a/packages/contracts/contracts/staking/IStakingExtension.sol b/packages/contracts/contracts/staking/IStakingExtension.sol deleted file mode 100644 index 9a998aac5..000000000 --- a/packages/contracts/contracts/staking/IStakingExtension.sol +++ /dev/null @@ -1,292 +0,0 @@ -// 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); -} diff --git a/packages/contracts/contracts/staking/L1Staking.sol b/packages/contracts/contracts/staking/L1Staking.sol index 78ce8bc63..b2a00c57e 100644 --- a/packages/contracts/contracts/staking/L1Staking.sol +++ b/packages/contracts/contracts/staking/L1Staking.sol @@ -3,23 +3,27 @@ pragma solidity ^0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable function-max-lines, gas-strict-inequalities + import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; -import { ITokenGateway } from "../arbitrum/ITokenGateway.sol"; +import { ITokenGateway } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol"; import { Staking } from "./Staking.sol"; import { Stakes } from "./libs/Stakes.sol"; -import { IStakes } from "./libs/IStakes.sol"; -import { IStakingData } from "./IStakingData.sol"; +import { IStakes } from "@graphprotocol/interfaces/contracts/contracts/staking/libs/IStakes.sol"; +import { IStakingData } from "@graphprotocol/interfaces/contracts/contracts/staking/IStakingData.sol"; import { L1StakingV1Storage } from "./L1StakingStorage.sol"; -import { IGraphToken } from "../token/IGraphToken.sol"; -import { IL1StakingBase } from "./IL1StakingBase.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; +import { IL1StakingBase } from "@graphprotocol/interfaces/contracts/contracts/staking/IL1StakingBase.sol"; import { MathUtils } from "./libs/MathUtils.sol"; -import { IL1GraphTokenLockTransferTool } from "./IL1GraphTokenLockTransferTool.sol"; -import { IL2StakingTypes } from "../l2/staking/IL2StakingTypes.sol"; +import { IL1GraphTokenLockTransferTool } from "@graphprotocol/interfaces/contracts/contracts/staking/IL1GraphTokenLockTransferTool.sol"; +import { IL2StakingTypes } from "@graphprotocol/interfaces/contracts/contracts/l2/staking/IL2StakingTypes.sol"; /** * @title L1Staking contract - * @dev This contract is the L1 variant of the Staking contract. It adds functions + * @author Edge & Node + * @notice This contract is the L1 variant of the Staking contract. It adds functions * to send an indexer's stake to L2, and to send delegation to L2 as well. */ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { @@ -36,9 +40,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { } /** - * @notice Set the L1GraphTokenLockTransferTool contract address - * @dev This function can only be called by the governor. - * @param _l1GraphTokenLockTransferTool Address of the L1GraphTokenLockTransferTool contract + * @inheritdoc IL1StakingBase */ function setL1GraphTokenLockTransferTool( IL1GraphTokenLockTransferTool _l1GraphTokenLockTransferTool @@ -48,21 +50,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { } /** - * @notice Send an indexer's stake to L2. - * @dev This function can only be called by the indexer (not an operator). - * It will validate that the remaining stake is sufficient to cover all the allocated - * stake, so the indexer might have to close some allocations before transferring. - * It will also check that the indexer's stake is not locked for withdrawal. - * Since the indexer address might be an L1-only contract, the function takes a beneficiary - * address that will be the indexer's address in L2. - * The caller must provide an amount of ETH to use for the L2 retryable ticket, that - * must be at _exactly_ `_maxSubmissionCost + _gasPriceBid * _maxGas`. - * Any refunds for the submission fee or L2 gas will be lost. - * @param _l2Beneficiary Address of the indexer in L2. If the indexer has previously transferred stake, this must match the previously-used value. - * @param _amount Amount of stake GRT to transfer to L2 - * @param _maxGas Max gas to use for the L2 retryable ticket - * @param _gasPriceBid Gas price bid for the L2 retryable ticket - * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket + * @inheritdoc IL1StakingBase */ function transferStakeToL2( address _l2Beneficiary, @@ -76,22 +64,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { } /** - * @notice Send an indexer's stake to L2, from a GraphTokenLockWallet vesting contract. - * @dev This function can only be called by the indexer (not an operator). - * It will validate that the remaining stake is sufficient to cover all the allocated - * stake, so the indexer might have to close some allocations before transferring. - * It will also check that the indexer's stake is not locked for withdrawal. - * The L2 beneficiary for the stake will be determined by calling the L1GraphTokenLockTransferTool contract, - * so the caller must have previously transferred tokens through that first - * (see GIP-0046 for details: https://forum.thegraph.com/t/4023). - * The ETH for the L2 gas will be pulled from the L1GraphTokenLockTransferTool, so the owner of - * the GraphTokenLockWallet must have previously deposited at least `_maxSubmissionCost + _gasPriceBid * _maxGas` - * ETH into the L1GraphTokenLockTransferTool contract (using its depositETH function). - * Any refunds for the submission fee or L2 gas will be lost. - * @param _amount Amount of stake GRT to transfer to L2 - * @param _maxGas Max gas to use for the L2 retryable ticket - * @param _gasPriceBid Gas price bid for the L2 retryable ticket - * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket + * @inheritdoc IL1StakingBase */ function transferLockedStakeToL2( uint256 _amount, @@ -109,20 +82,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { } /** - * @notice Send a delegator's delegated tokens to L2 - * @dev This function can only be called by the delegator. - * This function will validate that the indexer has transferred their stake using transferStakeToL2, - * and that the delegation is not locked for undelegation. - * Since the delegator's address might be an L1-only contract, the function takes a beneficiary - * address that will be the delegator's address in L2. - * The caller must provide an amount of ETH to use for the L2 retryable ticket, that - * must be _exactly_ `_maxSubmissionCost + _gasPriceBid * _maxGas`. - * Any refunds for the submission fee or L2 gas will be lost. - * @param _indexer Address of the indexer (in L1, before transferring to L2) - * @param _l2Beneficiary Address of the delegator in L2 - * @param _maxGas Max gas to use for the L2 retryable ticket - * @param _gasPriceBid Gas price bid for the L2 retryable ticket - * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket + * @inheritdoc IL1StakingBase */ function transferDelegationToL2( address _indexer, @@ -144,21 +104,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { } /** - * @notice Send a delegator's delegated tokens to L2, for a GraphTokenLockWallet vesting contract - * @dev This function can only be called by the delegator. - * This function will validate that the indexer has transferred their stake using transferStakeToL2, - * and that the delegation is not locked for undelegation. - * The L2 beneficiary for the delegation will be determined by calling the L1GraphTokenLockTransferTool contract, - * so the caller must have previously transferred tokens through that first - * (see GIP-0046 for details: https://forum.thegraph.com/t/4023). - * The ETH for the L2 gas will be pulled from the L1GraphTokenLockTransferTool, so the owner of - * the GraphTokenLockWallet must have previously deposited at least `_maxSubmissionCost + _gasPriceBid * _maxGas` - * ETH into the L1GraphTokenLockTransferTool contract (using its depositETH function). - * Any refunds for the submission fee or L2 gas will be lost. - * @param _indexer Address of the indexer (in L1, before transferring to L2) - * @param _maxGas Max gas to use for the L2 retryable ticket - * @param _gasPriceBid Gas price bid for the L2 retryable ticket - * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket + * @inheritdoc IL1StakingBase */ function transferLockedDelegationToL2( address _indexer, @@ -184,13 +130,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { } /** - * @notice Unlock a delegator's delegated tokens, if the indexer has transferred to L2 - * @dev This function can only be called by the delegator. - * This function will validate that the indexer has transferred their stake using transferStakeToL2, - * and that the indexer has no remaining stake in L1. - * The tokens must previously be locked for undelegation by calling `undelegate()`, - * and can be withdrawn with `withdrawDelegated()` immediately after calling this. - * @param _indexer Address of the indexer (in L1, before transferring to L2) + * @inheritdoc IL1StakingBase */ function unlockDelegationToTransferredIndexer(address _indexer) external override notPartialPaused { require( @@ -209,13 +149,14 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { } /** - * @dev Implements sending an indexer's stake to L2. + * @notice Implements sending an indexer's stake to L2. * This function can only be called by the indexer (not an operator). * It will validate that the remaining stake is sufficient to cover all the allocated * stake, so the indexer might have to close some allocations before transferring. * It will also check that the indexer's stake is not locked for withdrawal. * Since the indexer address might be an L1-only contract, the function takes a beneficiary * address that will be the indexer's address in L2. + * @param _indexer Address of the indexer transferring stake * @param _l2Beneficiary Address of the indexer in L2. If the indexer has previously transferred stake, this must match the previously-used value. * @param _amount Amount of stake GRT to transfer to L2 * @param _maxGas Max gas to use for the L2 retryable ticket @@ -282,12 +223,13 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { } /** - * @dev Implements sending a delegator's delegated tokens to L2. + * @notice Implements sending a delegator's delegated tokens to L2. * This function can only be called by the delegator. * This function will validate that the indexer has transferred their stake using transferStakeToL2, * and that the delegation is not locked for undelegation. * Since the delegator's address might be an L1-only contract, the function takes a beneficiary * address that will be the delegator's address in L2. + * @param _delegator Address of the delegator transferring delegation * @param _indexer Address of the indexer (in L1, before transferring to L2) * @param _l2Beneficiary Address of the delegator in L2 * @param _maxGas Max gas to use for the L2 retryable ticket @@ -352,7 +294,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { } /** - * @dev Sends a message to the L2Staking with some extra data, + * @notice Sends a message to the L2Staking with some extra data, * also sending some tokens, using the L1GraphTokenGateway. * @param _tokens Amount of tokens to send to L2 * @param _maxGas Max gas to use for the L2 retryable ticket diff --git a/packages/contracts/contracts/staking/L1StakingStorage.sol b/packages/contracts/contracts/staking/L1StakingStorage.sol index bd7a7f0ee..5ee76f633 100644 --- a/packages/contracts/contracts/staking/L1StakingStorage.sol +++ b/packages/contracts/contracts/staking/L1StakingStorage.sol @@ -1,18 +1,22 @@ // SPDX-License-Identifier: GPL-2.0-or-later +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable named-parameters-mapping + pragma solidity ^0.7.6; pragma abicoder v2; -import { IL1GraphTokenLockTransferTool } from "./IL1GraphTokenLockTransferTool.sol"; +import { IL1GraphTokenLockTransferTool } from "@graphprotocol/interfaces/contracts/contracts/staking/IL1GraphTokenLockTransferTool.sol"; /** * @title L1StakingV1Storage + * @author Edge & Node * @notice This contract holds all the L1-specific storage variables for the L1Staking contract, version 1 * @dev When adding new versions, make sure to move the gap to the new version and * reduce the size of the gap accordingly. */ abstract contract L1StakingV1Storage { - /// If an indexer has transferred to L2, this mapping will hold the indexer's address in L2 + /// @notice If an indexer has transferred to L2, this mapping will hold the indexer's address in L2 mapping(address => address) public indexerTransferredToL2; /// @dev For locked indexers/delegations, this contract holds the mapping of L1 to L2 addresses IL1GraphTokenLockTransferTool internal l1GraphTokenLockTransferTool; diff --git a/packages/contracts/contracts/staking/Staking.sol b/packages/contracts/contracts/staking/Staking.sol index c61fe0ded..4b7551d02 100644 --- a/packages/contracts/contracts/staking/Staking.sol +++ b/packages/contracts/contracts/staking/Staking.sol @@ -3,27 +3,31 @@ pragma solidity ^0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable function-max-lines, gas-strict-inequalities + import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; import { ECDSA } from "@openzeppelin/contracts/cryptography/ECDSA.sol"; import { Multicall } from "../base/Multicall.sol"; import { GraphUpgradeable } from "../upgrades/GraphUpgradeable.sol"; import { TokenUtils } from "../utils/TokenUtils.sol"; -import { IGraphToken } from "../token/IGraphToken.sol"; -import { IStakingBase } from "./IStakingBase.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; +import { IStakingBase } from "@graphprotocol/interfaces/contracts/contracts/staking/IStakingBase.sol"; import { StakingV4Storage } from "./StakingStorage.sol"; import { MathUtils } from "./libs/MathUtils.sol"; import { Stakes } from "./libs/Stakes.sol"; -import { IStakes } from "./libs/IStakes.sol"; +import { IStakes } from "@graphprotocol/interfaces/contracts/contracts/staking/libs/IStakes.sol"; import { Managed } from "../governance/Managed.sol"; -import { ICuration } from "../curation/ICuration.sol"; -import { IRewardsManager } from "../rewards/IRewardsManager.sol"; +import { ICuration } from "@graphprotocol/interfaces/contracts/contracts/curation/ICuration.sol"; +import { IRewardsManager } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsManager.sol"; import { StakingExtension } from "./StakingExtension.sol"; import { LibExponential } from "./libs/Exponential.sol"; /** * @title Base Staking contract - * @dev The Staking contract allows Indexers to Stake on Subgraphs. Indexers Stake by creating + * @author Edge & Node + * @notice The Staking contract allows Indexers to Stake on Subgraphs. Indexers Stake by creating * Allocations on a Subgraph. It also allows Delegators to Delegate towards an Indexer. The * contract also has the slashing functionality. * The contract is abstract as the implementation that is deployed depends on each layer: L1Staking on mainnet @@ -45,9 +49,11 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M * @dev This function does not return to its internal call site, it will return directly to the * external caller. */ - // solhint-disable-next-line payable-fallback, no-complex-fallback fallback() external { + // solhint-disable-previous-line payable-fallback, no-complex-fallback + require(_implementation() != address(0), "only through proxy"); + // solhint-disable-next-line no-inline-assembly assembly { // (a) get free memory pointer @@ -80,17 +86,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @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 epochs 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 + * @inheritdoc IStakingBase */ function initialize( address _controller, @@ -140,9 +136,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @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 + * @inheritdoc IStakingBase */ function setExtensionImpl(address _extensionImpl) external override onlyGovernor { extensionImpl = _extensionImpl; @@ -150,9 +144,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @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. + * @inheritdoc IStakingBase */ function setCounterpartStakingAddress(address _counterpart) external override onlyGovernor { counterpartStakingAddress = _counterpart; @@ -160,52 +152,42 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @notice Set the minimum stake required to be an indexer. - * @param _minimumIndexerStake Minimum indexer stake + * @inheritdoc IStakingBase */ function setMinimumIndexerStake(uint256 _minimumIndexerStake) external override onlyGovernor { _setMinimumIndexerStake(_minimumIndexerStake); } /** - * @notice Set the thawing period for unstaking. - * @param _thawingPeriod Period in blocks to wait for token withdrawals after unstaking + * @inheritdoc IStakingBase */ function setThawingPeriod(uint32 _thawingPeriod) external override onlyGovernor { _setThawingPeriod(_thawingPeriod); } /** - * @notice Set the curation percentage of query fees sent to curators. - * @param _percentage Percentage of query fees sent to curators + * @inheritdoc IStakingBase */ function setCurationPercentage(uint32 _percentage) external override onlyGovernor { _setCurationPercentage(_percentage); } /** - * @notice Set a protocol percentage to burn when collecting query fees. - * @param _percentage Percentage of query fees to burn as protocol fee + * @inheritdoc IStakingBase */ function setProtocolPercentage(uint32 _percentage) external override onlyGovernor { _setProtocolPercentage(_percentage); } /** - * @notice Set the max time allowed for indexers to allocate on a subgraph - * before others are allowed to close the allocation. - * @param _maxAllocationEpochs Allocation duration limit in epochs + * @inheritdoc IStakingBase */ function setMaxAllocationEpochs(uint32 _maxAllocationEpochs) external override onlyGovernor { _setMaxAllocationEpochs(_maxAllocationEpochs); } /** - * @dev Set the rebate parameters. - * @param _alphaNumerator Numerator of `alpha` in the rebates function - * @param _alphaDenominator Denominator of `alpha` in the rebates function - * @param _lambdaNumerator Numerator of `lambda` in the rebates function - * @param _lambdaDenominator Denominator of `lambda` in the rebates function + * @inheritdoc IStakingBase */ function setRebateParameters( uint32 _alphaNumerator, @@ -217,9 +199,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @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 + * @inheritdoc IStakingBase */ function setOperator(address _operator, bool _allowed) external override { require(_operator != msg.sender, "operator == sender"); @@ -228,21 +208,18 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @notice Deposit tokens on the indexer's stake. - * The amount staked must be over the minimumIndexerStake. - * @param _tokens Amount of tokens to stake + * @inheritdoc IStakingBase */ function stake(uint256 _tokens) external override { stakeTo(msg.sender, _tokens); } /** - * @notice Unstake tokens from the indexer stake, lock them until the thawing period expires. + * @inheritdoc IStakingBase * @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 override notPartialPaused { address indexer = msg.sender; @@ -271,15 +248,14 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @notice Withdraw indexer tokens once the thawing period has passed. + * @inheritdoc IStakingBase */ function withdraw() external override notPaused { _withdraw(msg.sender); } /** - * @notice Set the destination where to send rewards for an indexer. - * @param _destination Rewards destination address. If set to zero, rewards will be restaked + * @inheritdoc IStakingBase */ function setRewardsDestination(address _destination) external override { __rewardsDestination[msg.sender] = _destination; @@ -287,12 +263,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @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)` + * @inheritdoc IStakingBase */ function allocate( bytes32 _subgraphDeploymentID, @@ -305,14 +276,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @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)` + * @inheritdoc IStakingBase */ function allocateFrom( address _indexer, @@ -326,25 +290,20 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @notice Close an allocation and free the staked tokens. - * To be eligible for rewards a proof of indexing must be presented. + * @inheritdoc IStakingBase + * @dev 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 override notPaused { _closeAllocation(_allocationID, _poi); } /** - * @dev Collect and rebate query fees from state channels to the indexer - * To avoid reverting on the withdrawal from channel flow this function will accept calls with zero tokens. - * We use an exponential rebate formula to calculate the amount of tokens to rebate to the indexer. + * @inheritdoc IStakingBase + * @dev We use an exponential rebate formula to calculate the amount of tokens to rebate to the indexer. * This implementation allows collecting multiple times on the same allocation, keeping track of the * total amount rebated, the total amount collected and compensating the indexer for the difference. - * @param _tokens Amount of tokens to collect - * @param _allocationID Allocation where the tokens will be assigned */ function collect(uint256 _tokens, address _allocationID) external override { // Allocation identifier validation @@ -447,36 +406,28 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @notice Return if allocationID is used. - * @param _allocationID Address used as signer by the indexer for an allocation - * @return True if allocationID already used + * @inheritdoc IStakingBase */ function isAllocation(address _allocationID) external view override returns (bool) { return _getAllocationState(_allocationID) != AllocationState.Null; } /** - * @notice Getter that returns if an indexer has any stake. - * @param _indexer Address of the indexer - * @return True if indexer has staked tokens + * @inheritdoc IStakingBase */ function hasStake(address _indexer) external view override returns (bool) { return __stakes[_indexer].tokensStaked > 0; } /** - * @notice Return the allocation by ID. - * @param _allocationID Address used as allocation identifier - * @return Allocation data + * @inheritdoc IStakingBase */ function getAllocation(address _allocationID) external view override returns (Allocation memory) { return __allocations[_allocationID]; } /** - * @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. + * @inheritdoc IStakingBase */ function getAllocationData( address _allocationID @@ -495,46 +446,35 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @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. + * @inheritdoc IStakingBase */ function isActiveAllocation(address _allocationID) external view override returns (bool) { return _getAllocationState(_allocationID) == AllocationState.Active; } /** - * @notice Return the current state of an allocation - * @param _allocationID Allocation identifier - * @return AllocationState enum with the state of the allocation + * @inheritdoc IStakingBase */ function getAllocationState(address _allocationID) external view override returns (AllocationState) { return _getAllocationState(_allocationID); } /** - * @notice Return the total amount of tokens allocated to subgraph. - * @param _subgraphDeploymentID Deployment ID for the subgraph - * @return Total tokens allocated to subgraph + * @inheritdoc IStakingBase */ function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentID) external view override returns (uint256) { return __subgraphAllocations[_subgraphDeploymentID]; } /** - * @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 + * @inheritdoc IStakingBase */ function getIndexerStakedTokens(address _indexer) external view override returns (uint256) { return __stakes[_indexer].tokensStaked; } /** - * @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 + * @inheritdoc IStakingBase */ function stakeTo(address _indexer, uint256 _tokens) public override notPartialPaused { require(_tokens > 0, "!tokens"); @@ -547,9 +487,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @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 + * @inheritdoc IStakingBase */ function setDelegationParameters( uint32 _indexingRewardCut, @@ -560,10 +498,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @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 + * @inheritdoc IStakingBase */ function getIndexerCapacity(address _indexer) public view override returns (uint256) { IStakes.Indexer memory indexerStake = __stakes[_indexer]; @@ -576,17 +511,14 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @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 + * @inheritdoc IStakingBase */ function isOperator(address _operator, address _indexer) public view override returns (bool) { return __operatorAuth[_indexer][_operator]; } /** - * @dev Internal: Set the minimum indexer stake required. + * @notice Internal: Set the minimum indexer stake required. * @param _minimumIndexerStake Minimum indexer stake */ function _setMinimumIndexerStake(uint256 _minimumIndexerStake) private { @@ -596,7 +528,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Internal: Set the thawing period for unstaking. + * @notice Internal: Set the thawing period for unstaking. * @param _thawingPeriod Period in blocks to wait for token withdrawals after unstaking */ function _setThawingPeriod(uint32 _thawingPeriod) private { @@ -606,7 +538,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Internal: Set the curation percentage of query fees sent to curators. + * @notice Internal: Set the curation percentage of query fees sent to curators. * @param _percentage Percentage of query fees sent to curators */ function _setCurationPercentage(uint32 _percentage) private { @@ -617,7 +549,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Internal: Set a protocol percentage to burn when collecting query fees. + * @notice Internal: Set a protocol percentage to burn when collecting query fees. * @param _percentage Percentage of query fees to burn as protocol fee */ function _setProtocolPercentage(uint32 _percentage) private { @@ -628,7 +560,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Internal: Set the max time allowed for indexers stake on allocations. + * @notice Internal: Set the max time allowed for indexers stake on allocations. * @param _maxAllocationEpochs Allocation duration limit in epochs */ function _setMaxAllocationEpochs(uint32 _maxAllocationEpochs) private { @@ -637,7 +569,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Set the rebate parameters. + * @notice Set the rebate parameters. * @param _alphaNumerator Numerator of `alpha` in the rebates function * @param _alphaDenominator Denominator of `alpha` in the rebates function * @param _lambdaNumerator Numerator of `lambda` in the rebates function @@ -660,7 +592,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Set the delegation parameters for a particular indexer. + * @notice Set the delegation parameters for a particular indexer. * @param _indexer Indexer to set delegation parameters * @param _indexingRewardCut Percentage of indexing rewards left for delegators * @param _queryFeeCut Percentage of query fees left for delegators @@ -681,7 +613,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Stake tokens on the indexer. + * @notice Stake tokens on the indexer. * This function does not check minimum indexer stake requirement to allow * to be called by functions that increase the stake when collecting rewards * without reverting @@ -704,7 +636,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Withdraw indexer tokens once the thawing period has passed. + * @notice Withdraw indexer tokens once the thawing period has passed. * @param _indexer Address of indexer to withdraw funds from */ function _withdraw(address _indexer) private { @@ -719,7 +651,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Allocate available tokens to a subgraph deployment. + * @notice Allocate available tokens to a subgraph deployment. * @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 @@ -794,7 +726,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Close an allocation and free the staked tokens. + * @notice Close an allocation and free the staked tokens. * @param _allocationID The allocation identifier * @param _poi Proof of indexing submitted for the allocated period */ @@ -861,7 +793,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Collect the delegation rewards for query fees. + * @notice Collect the delegation rewards for query fees. * This function will assign the collected fees to the delegation pool. * @param _indexer Indexer to which the tokens to distribute are related * @param _tokens Total tokens received used to calculate the amount of fees to collect @@ -879,7 +811,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Collect the delegation rewards for indexing. + * @notice Collect the delegation rewards for indexing. * This function will assign the collected fees to the delegation pool. * @param _indexer Indexer to which the tokens to distribute are related * @param _tokens Total tokens received used to calculate the amount of fees to collect @@ -897,7 +829,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Collect the curation fees for a subgraph deployment from an amount of tokens. + * @notice Collect the curation fees for a subgraph deployment from an amount of tokens. * This function transfer curation fees to the Curation contract by calling Curation.collect * @param _graphToken Token to collect * @param _subgraphDeploymentID Subgraph deployment to which the curation fees are related @@ -926,7 +858,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M if (curationFees > 0) { // Transfer and call collect() // This function transfer tokens to a trusted protocol contracts - // Then we call collect() to do the transfer Bookkeeping + // Then we call collect() to do the transfer bookkeeping rewardsManager().onSubgraphSignalUpdate(_subgraphDeploymentID); TokenUtils.pushTokens(_graphToken, address(curation), curationFees); curation.collect(_subgraphDeploymentID, curationFees); @@ -937,7 +869,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Collect tax to burn for an amount of tokens. + * @notice Collect tax to burn for an amount of tokens. * @param _graphToken Token to burn * @param _tokens Total tokens received used to calculate the amount of tax to collect * @param _percentage Percentage of tokens to burn as tax @@ -953,7 +885,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Triggers an update of rewards due to a change in allocations. + * @notice Triggers an update of rewards due to a change in allocations. * @param _subgraphDeploymentID Subgraph deployment updated * @return Accumulated rewards per allocated token for the subgraph deployment */ @@ -966,7 +898,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Assign rewards for the closed allocation to indexer and delegators. + * @notice Assign rewards for the closed allocation to indexer and delegators. * @param _allocationID Allocation * @param _indexer Address of the indexer that did the allocation */ @@ -993,7 +925,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Send rewards to the appropriate destination. + * @notice Send rewards to the appropriate destination. * @param _graphToken Graph token * @param _amount Number of rewards tokens * @param _beneficiary Address of the beneficiary of rewards @@ -1013,7 +945,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Check if the caller is authorized to operate on behalf of + * @notice Check if the caller is authorized to operate on behalf of * an indexer (i.e. the caller is the indexer or an operator) * @param _indexer Indexer address * @return True if the caller is authorized to operate on behalf of the indexer @@ -1023,7 +955,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } /** - * @dev Return the current state of an allocation + * @notice Return the current state of an allocation * @param _allocationID Allocation identifier * @return AllocationState enum with the state of the allocation */ diff --git a/packages/contracts/contracts/staking/StakingExtension.sol b/packages/contracts/contracts/staking/StakingExtension.sol index b06fbe894..8bde14add 100644 --- a/packages/contracts/contracts/staking/StakingExtension.sol +++ b/packages/contracts/contracts/staking/StakingExtension.sol @@ -3,20 +3,24 @@ pragma solidity ^0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities + import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; import { StakingV4Storage } from "./StakingStorage.sol"; -import { IStakingExtension } from "./IStakingExtension.sol"; +import { IStakingExtension } from "@graphprotocol/interfaces/contracts/contracts/staking/IStakingExtension.sol"; import { TokenUtils } from "../utils/TokenUtils.sol"; -import { IGraphToken } from "../token/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { GraphUpgradeable } from "../upgrades/GraphUpgradeable.sol"; -import { IStakes } from "./libs/IStakes.sol"; +import { IStakes } from "@graphprotocol/interfaces/contracts/contracts/staking/libs/IStakes.sol"; import { Stakes } from "./libs/Stakes.sol"; -import { IStakingData } from "./IStakingData.sol"; +import { IStakingData } from "@graphprotocol/interfaces/contracts/contracts/staking/IStakingData.sol"; import { MathUtils } from "./libs/MathUtils.sol"; /** * @title StakingExtension contract - * @dev This contract provides the logic to manage delegations and other Staking + * @author Edge & Node + * @notice This contract provides the logic to manage delegations and other Staking * extension features (e.g. storage getters). It is meant to be called through delegatecall from the * Staking contract, and is only kept separate to keep the Staking contract size * within limits. @@ -44,12 +48,14 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * initialize() function, so it uses the same access control check to ensure it is * being called by the Staking implementation as part of the proxy upgrade process. * @param _delegationUnbondingPeriod Delegation unbonding period in blocks + * @param _cooldownBlocks Deprecated parameter (no longer used) * @param _delegationRatio Delegation capacity multiplier (e.g. 10 means 10x the indexer stake) * @param _delegationTaxPercentage Percentage of delegated tokens to burn as delegation tax, expressed in parts per million */ function initialize( uint32 _delegationUnbondingPeriod, - uint32, //_cooldownBlocks, deprecated + // solhint-disable-next-line no-unused-vars + uint32 _cooldownBlocks, // deprecated uint32 _delegationRatio, uint32 _delegationTaxPercentage ) external onlyImpl { @@ -59,38 +65,28 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi } /** - * @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 + * @inheritdoc IStakingExtension */ function setDelegationTaxPercentage(uint32 _percentage) external override onlyGovernor { _setDelegationTaxPercentage(_percentage); } /** - * @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 + * @inheritdoc IStakingExtension */ function setDelegationRatio(uint32 _delegationRatio) external override onlyGovernor { _setDelegationRatio(_delegationRatio); } /** - * @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 + * @inheritdoc IStakingExtension */ function setDelegationUnbondingPeriod(uint32 _delegationUnbondingPeriod) external override onlyGovernor { _setDelegationUnbondingPeriod(_delegationUnbondingPeriod); } /** - * @notice Set or unset an address as allowed slasher. - * @param _slasher Address of the party allowed to slash indexers - * @param _allowed True if slasher is allowed + * @inheritdoc IStakingExtension */ function setSlasher(address _slasher, bool _allowed) external override onlyGovernor { require(_slasher != address(0), "!slasher"); @@ -99,10 +95,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi } /** - * @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 + * @inheritdoc IStakingExtension */ function delegate(address _indexer, uint256 _tokens) external override notPartialPaused returns (uint256) { address delegator = msg.sender; @@ -115,32 +108,21 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi } /** - * @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 + * @inheritdoc IStakingExtension */ function undelegate(address _indexer, uint256 _shares) external override notPartialPaused returns (uint256) { return _undelegate(msg.sender, _indexer, _shares); } /** - * @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 + * @inheritdoc IStakingExtension */ function withdrawDelegated(address _indexer, address _newIndexer) external override notPaused returns (uint256) { return _withdrawDelegated(msg.sender, _indexer, _newIndexer); } /** - * @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 + * @inheritdoc IStakingExtension */ function slash( address _indexer, @@ -188,48 +170,35 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi } /** - * @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 + * @inheritdoc IStakingExtension */ function getDelegation(address _indexer, address _delegator) external view override returns (Delegation memory) { return __delegationPools[_indexer].delegators[_delegator]; } /** - * @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 + * @inheritdoc IStakingExtension */ function delegationRatio() external view override returns (uint32) { return __delegationRatio; } /** - * @notice Getter for delegationUnbondingPeriod: - * Time in epochs a delegator needs to wait to withdraw delegated stake - * @return Delegation unbonding period in epochs + * @inheritdoc IStakingExtension */ function delegationUnbondingPeriod() external view override returns (uint32) { return __delegationUnbondingPeriod; } /** - * @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 + * @inheritdoc IStakingExtension */ function delegationTaxPercentage() external view override returns (uint32) { return __delegationTaxPercentage; } /** - * @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 + * @inheritdoc IStakingExtension */ function delegationPools(address _indexer) external view override returns (DelegationPoolReturn memory) { DelegationPool storage pool = __delegationPools[_indexer]; @@ -245,120 +214,91 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi } /** - * @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 + * @inheritdoc IStakingExtension */ function rewardsDestination(address _indexer) external view override returns (address) { return __rewardsDestination[_indexer]; } /** - * @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 + * @inheritdoc IStakingExtension */ function operatorAuth(address _indexer, address _maybeOperator) external view override returns (bool) { return __operatorAuth[_indexer][_maybeOperator]; } /** - * @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 + * @inheritdoc IStakingExtension */ function subgraphAllocations(bytes32 _subgraphDeploymentId) external view override returns (uint256) { return __subgraphAllocations[_subgraphDeploymentId]; } /** - * @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 + * @inheritdoc IStakingExtension */ function slashers(address _maybeSlasher) external view override returns (bool) { return __slashers[_maybeSlasher]; } /** - * @notice Getter for minimumIndexerStake: the minimum - * amount of GRT that an indexer needs to stake. - * @return Minimum indexer stake in GRT + * @inheritdoc IStakingExtension */ function minimumIndexerStake() external view override returns (uint256) { return __minimumIndexerStake; } /** - * @notice Getter for thawingPeriod: the time in blocks an - * indexer needs to wait to unstake tokens. - * @return Thawing period in blocks + * @inheritdoc IStakingExtension */ function thawingPeriod() external view override returns (uint32) { return __thawingPeriod; } /** - * @notice Getter for curationPercentage: the percentage of - * query fees that are distributed to curators. - * @return Curation percentage in parts per million + * @inheritdoc IStakingExtension */ function curationPercentage() external view override returns (uint32) { return __curationPercentage; } /** - * @notice Getter for protocolPercentage: the percentage of - * query fees that are burned as protocol fees. - * @return Protocol percentage in parts per million + * @inheritdoc IStakingExtension */ function protocolPercentage() external view override returns (uint32) { return __protocolPercentage; } /** - * @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 + * @inheritdoc IStakingExtension */ function maxAllocationEpochs() external view override returns (uint32) { return __maxAllocationEpochs; } /** - * @notice Getter for the numerator of the rebates alpha parameter - * @return Alpha numerator + * @inheritdoc IStakingExtension */ function alphaNumerator() external view override returns (uint32) { return __alphaNumerator; } /** - * @notice Getter for the denominator of the rebates alpha parameter - * @return Alpha denominator + * @inheritdoc IStakingExtension */ function alphaDenominator() external view override returns (uint32) { return __alphaDenominator; } /** - * @notice Getter for the numerator of the rebates lambda parameter - * @return Lambda numerator + * @inheritdoc IStakingExtension */ function lambdaNumerator() external view override returns (uint32) { return __lambdaNumerator; } /** - * @notice Getter for the denominator of the rebates lambda parameter - * @return Lambda denominator + * @inheritdoc IStakingExtension */ function lambdaDenominator() external view override returns (uint32) { return __lambdaDenominator; @@ -369,35 +309,28 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * gets the stake information for an indexer as an IStakes.Indexer struct. * @param _indexer Indexer address for which to query the stake information * @return Stake information for the specified indexer, as an IStakes.Indexer struct + * @inheritdoc IStakingExtension */ function stakes(address _indexer) external view override returns (IStakes.Indexer memory) { return __stakes[_indexer]; } /** - * @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 + * @inheritdoc IStakingExtension */ function allocations(address _allocationID) external view override returns (IStakingData.Allocation memory) { return __allocations[_allocationID]; } /** - * @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 + * @inheritdoc IStakingExtension */ function isDelegator(address _indexer, address _delegator) public view override returns (bool) { return __delegationPools[_indexer].delegators[_delegator].shares > 0; } /** - * @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 + * @inheritdoc IStakingExtension */ function getWithdraweableDelegatedTokens(Delegation memory _delegation) public view override returns (uint256) { // There must be locked tokens and period passed @@ -409,7 +342,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi } /** - * @dev Internal: Set a delegation tax percentage to burn when delegated funds are deposited. + * @notice Internal: Set a delegation tax percentage to burn when delegated funds are deposited. * @param _percentage Percentage of delegated tokens to burn as delegation tax */ function _setDelegationTaxPercentage(uint32 _percentage) private { @@ -420,7 +353,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi } /** - * @dev Internal: Set the delegation ratio. + * @notice Internal: 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 * @param _delegationRatio Delegation capacity multiplier @@ -431,7 +364,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi } /** - * @dev Internal: Set the period for undelegation of stake from indexer. + * @notice Internal: Set the period for undelegation of stake from indexer. * @param _delegationUnbondingPeriod Period in epochs to wait for token withdrawals after undelegating */ function _setDelegationUnbondingPeriod(uint32 _delegationUnbondingPeriod) private { @@ -441,7 +374,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi } /** - * @dev Delegate tokens to an indexer. + * @notice Delegate tokens to an indexer. * @param _delegator Address of the delegator * @param _indexer Address of the indexer to delegate tokens to * @param _tokens Amount of tokens to delegate @@ -480,7 +413,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi } /** - * @dev Undelegate tokens from an indexer. + * @notice Undelegate tokens from an indexer. * @param _delegator Address of the delegator * @param _indexer Address of the indexer where tokens had been delegated * @param _shares Amount of shares to return and undelegate tokens @@ -531,7 +464,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi } /** - * @dev Withdraw delegated tokens once the unbonding period has passed. + * @notice Withdraw delegated tokens once the unbonding period has passed. * @param _delegator Delegator that is withdrawing tokens * @param _indexer Withdraw available tokens delegated to indexer * @param _delegateToIndexer Re-delegate to indexer address if non-zero, withdraw if zero address @@ -570,7 +503,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi } /** - * @dev Collect tax to burn for an amount of tokens. + * @notice Collect tax to burn for an amount of tokens. * @param _graphToken Token to burn * @param _tokens Total tokens received used to calculate the amount of tax to collect * @param _percentage Percentage of tokens to burn as tax diff --git a/packages/contracts/contracts/staking/StakingStorage.sol b/packages/contracts/contracts/staking/StakingStorage.sol index 949a63614..24f46009f 100644 --- a/packages/contracts/contracts/staking/StakingStorage.sol +++ b/packages/contracts/contracts/staking/StakingStorage.sol @@ -1,19 +1,24 @@ // SPDX-License-Identifier: GPL-2.0-or-later +// solhint-disable one-contract-per-file pragma solidity ^0.7.6; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable one-contract-per-file, max-states-count +// solhint-disable named-parameters-mapping + import { Managed } from "../governance/Managed.sol"; -import { IStakingData } from "./IStakingData.sol"; -import { IStakes } from "./libs/IStakes.sol"; +import { IStakingData } from "@graphprotocol/interfaces/contracts/contracts/staking/IStakingData.sol"; +import { IStakes } from "@graphprotocol/interfaces/contracts/contracts/staking/libs/IStakes.sol"; /** * @title StakingV1Storage + * @author Edge & Node * @notice This contract holds all the storage variables for the Staking contract, version 1 * @dev Note that we use a double underscore prefix for variable names; this prefix identifies * variables that used to be public but are now internal, getters can be found on StakingExtension.sol. */ -// solhint-disable-next-line max-states-count contract StakingV1Storage is Managed { // -- Staking -- @@ -54,7 +59,7 @@ contract StakingV1Storage is Managed { /// @dev Subgraph Allocations: subgraphDeploymentID => tokens mapping(bytes32 => uint256) internal __subgraphAllocations; - // Rebate pools : epoch => Pool + /// @dev Deprecated rebate pools mapping (no longer used) mapping(uint256 => uint256) private __DEPRECATED_rebates; // solhint-disable-line var-name-mixedcase // -- Slashing -- @@ -95,6 +100,7 @@ contract StakingV1Storage is Managed { /** * @title StakingV2Storage + * @author Edge & Node * @notice This contract holds all the storage variables for the Staking contract, version 2 * @dev Note that we use a double underscore prefix for variable names; this prefix identifies * variables that used to be public but are now internal, getters can be found on StakingExtension.sol. @@ -106,6 +112,7 @@ contract StakingV2Storage is StakingV1Storage { /** * @title StakingV3Storage + * @author Edge & Node * @notice This contract holds all the storage variables for the base Staking contract, version 3. */ contract StakingV3Storage is StakingV2Storage { @@ -117,13 +124,15 @@ contract StakingV3Storage is StakingV2Storage { /** * @title StakingV4Storage + * @author Edge & Node * @notice This contract holds all the storage variables for the base Staking contract, version 4. * @dev Note that it includes a storage gap - if adding future versions, make sure to move the gap * to the new version and reduce the size of the gap accordingly. */ contract StakingV4Storage is StakingV3Storage { - // Additional rebate parameters for exponential rebates + /// @dev Numerator for the lambda parameter in exponential rebate calculations uint32 internal __lambdaNumerator; + /// @dev Denominator for the lambda parameter in exponential rebate calculations uint32 internal __lambdaDenominator; /// @dev Gap to allow adding variables in future upgrades (since L1Staking and L2Staking can have their own storage as well) diff --git a/packages/contracts/contracts/staking/libs/Exponential.sol b/packages/contracts/contracts/staking/libs/Exponential.sol index c9370342e..2b0222daa 100644 --- a/packages/contracts/contracts/staking/libs/Exponential.sol +++ b/packages/contracts/contracts/staking/libs/Exponential.sol @@ -6,13 +6,14 @@ import { LibFixedMath } from "./LibFixedMath.sol"; /** * @title LibExponential library + * @author Edge & Node * @notice A library to compute query fee rebates using an exponential formula */ library LibExponential { /// @dev Maximum value of the exponent for which to compute the exponential before clamping to zero. uint32 private constant MAX_EXPONENT = 15; - /// @dev The exponential formula used to compute fee-based rewards for + /// @notice The exponential formula used to compute fee-based rewards for /// staking pools in a given epoch. This function does not perform /// bounds checking on the inputs, but the following conditions /// need to be true: diff --git a/packages/contracts/contracts/staking/libs/IStakes.sol b/packages/contracts/contracts/staking/libs/IStakes.sol deleted file mode 100644 index 701336409..000000000 --- a/packages/contracts/contracts/staking/libs/IStakes.sol +++ /dev/null @@ -1,13 +0,0 @@ -// 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 - } -} diff --git a/packages/contracts/contracts/staking/libs/LibFixedMath.sol b/packages/contracts/contracts/staking/libs/LibFixedMath.sol index ae8c9b69e..55628ea6e 100644 --- a/packages/contracts/contracts/staking/libs/LibFixedMath.sol +++ b/packages/contracts/contracts/staking/libs/LibFixedMath.sol @@ -20,36 +20,49 @@ pragma solidity ^0.7.6; -// solhint-disable indent -/// @dev Signed, fixed-point, 127-bit precision math library. +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable function-max-lines, gas-strict-inequalities + +/** + * @title LibFixedMath + * @author Edge & Node + * @notice Signed, fixed-point, 127-bit precision math library + */ library LibFixedMath { - // 1 + /// @dev Fixed-point representation of 1 int256 private constant FIXED_1 = int256(0x0000000000000000000000000000000080000000000000000000000000000000); - // 2**255 + /// @dev Minimum fixed-point value (2**255) int256 private constant MIN_FIXED_VAL = int256(0x8000000000000000000000000000000000000000000000000000000000000000); - // 1^2 (in fixed-point) + /// @dev Fixed-point representation of 1^2 int256 private constant FIXED_1_SQUARED = int256(0x4000000000000000000000000000000000000000000000000000000000000000); - // 1 + /// @dev Maximum value for natural logarithm calculation int256 private constant LN_MAX_VAL = FIXED_1; - // e ^ -63.875 + /// @dev Minimum value for natural logarithm calculation (e ^ -63.875) int256 private constant LN_MIN_VAL = int256(0x0000000000000000000000000000000000000000000000000000000733048c5a); - // 0 + /// @dev Maximum value for exponentiation calculation int256 private constant EXP_MAX_VAL = 0; - // -63.875 + /// @dev Minimum value for exponentiation calculation (-63.875) int256 private constant EXP_MIN_VAL = -int256(0x0000000000000000000000000000001ff0000000000000000000000000000000); - /// @dev Get one as a fixed-point number. + /// @notice Get one as a fixed-point number. + /// @return f The fixed-point representation of 1 function one() internal pure returns (int256 f) { f = FIXED_1; } - /// @dev Returns the addition of two fixed point numbers, reverting on overflow. + /// @notice Returns the addition of two fixed point numbers, reverting on overflow. + /// @param a First fixed-point number + /// @param b Second fixed-point number + /// @return c The sum of a and b function add(int256 a, int256 b) internal pure returns (int256 c) { c = _add(a, b); } - /// @dev Returns the addition of two fixed point numbers, reverting on overflow. + /// @notice Returns the subtraction of two fixed point numbers, reverting on overflow. + /// @param a First fixed-point number + /// @param b Second fixed-point number + /// @return c The difference a - b function sub(int256 a, int256 b) internal pure returns (int256 c) { if (b == MIN_FIXED_VAL) { revert("out-of-bounds"); @@ -57,24 +70,37 @@ library LibFixedMath { c = _add(a, -b); } - /// @dev Returns the multiplication of two fixed point numbers, reverting on overflow. + /// @notice Returns the multiplication of two fixed point numbers, reverting on overflow. + /// @param a First fixed-point number + /// @param b Second fixed-point number + /// @return c The product of a and b function mul(int256 a, int256 b) internal pure returns (int256 c) { c = _mul(a, b) / FIXED_1; } - /// @dev Returns the division of two fixed point numbers. + /// @notice Returns the division of two fixed point numbers. + /// @param a Dividend fixed-point number + /// @param b Divisor fixed-point number + /// @return c The quotient a / b function div(int256 a, int256 b) internal pure returns (int256 c) { c = _div(_mul(a, FIXED_1), b); } - /// @dev Performs (a * n) / d, without scaling for precision. + /// @notice Performs (a * n) / d, without scaling for precision. + /// @param a First operand + /// @param n Numerator + /// @param d Denominator + /// @return c The result of (a * n) / d function mulDiv(int256 a, int256 n, int256 d) internal pure returns (int256 c) { c = _div(_mul(a, n), d); } - /// @dev Returns the unsigned integer result of multiplying a fixed-point + /// @notice Returns the unsigned integer result of multiplying a fixed-point /// number with an integer, reverting if the multiplication overflows. /// Negative results are clamped to zero. + /// @param f Fixed-point number + /// @param u Unsigned integer + /// @return The result of f * u as an unsigned integer function uintMul(int256 f, uint256 u) internal pure returns (uint256) { if (int256(u) < int256(0)) { revert("out-of-bounds"); @@ -86,7 +112,9 @@ library LibFixedMath { return uint256(uint256(c) >> 127); } - /// @dev Returns the absolute value of a fixed point number. + /// @notice Returns the absolute value of a fixed point number. + /// @param f Fixed-point number + /// @return c The absolute value of f function abs(int256 f) internal pure returns (int256 c) { if (f == MIN_FIXED_VAL) { revert("out-of-bounds"); @@ -98,23 +126,32 @@ library LibFixedMath { } } - /// @dev Returns 1 / `x`, where `x` is a fixed-point number. + /// @notice Returns 1 / `x`, where `x` is a fixed-point number. + /// @param f Fixed-point number to invert + /// @return c The reciprocal of f function invert(int256 f) internal pure returns (int256 c) { c = _div(FIXED_1_SQUARED, f); } - /// @dev Convert signed `n` / 1 to a fixed-point number. + /// @notice Convert signed `n` / 1 to a fixed-point number. + /// @param n Signed integer to convert + /// @return f The fixed-point representation of n function toFixed(int256 n) internal pure returns (int256 f) { f = _mul(n, FIXED_1); } - /// @dev Convert signed `n` / `d` to a fixed-point number. + /// @notice Convert signed `n` / `d` to a fixed-point number. + /// @param n Numerator + /// @param d Denominator + /// @return f The fixed-point representation of n/d function toFixed(int256 n, int256 d) internal pure returns (int256 f) { f = _div(_mul(n, FIXED_1), d); } - /// @dev Convert unsigned `n` / 1 to a fixed-point number. + /// @notice Convert unsigned `n` / 1 to a fixed-point number. /// Reverts if `n` is too large to fit in a fixed-point number. + /// @param n Unsigned integer to convert + /// @return f The fixed-point representation of n function toFixed(uint256 n) internal pure returns (int256 f) { if (int256(n) < int256(0)) { revert("out-of-bounds"); @@ -122,8 +159,11 @@ library LibFixedMath { f = _mul(int256(n), FIXED_1); } - /// @dev Convert unsigned `n` / `d` to a fixed-point number. + /// @notice Convert unsigned `n` / `d` to a fixed-point number. /// Reverts if `n` / `d` is too large to fit in a fixed-point number. + /// @param n Numerator + /// @param d Denominator + /// @return f The fixed-point representation of n/d function toFixed(uint256 n, uint256 d) internal pure returns (int256 f) { if (int256(n) < int256(0)) { revert("out-of-bounds"); @@ -134,12 +174,16 @@ library LibFixedMath { f = _div(_mul(int256(n), FIXED_1), int256(d)); } - /// @dev Convert a fixed-point number to an integer. + /// @notice Convert a fixed-point number to an integer. + /// @param f Fixed-point number to convert + /// @return n The integer representation of f function toInteger(int256 f) internal pure returns (int256 n) { return f / FIXED_1; } - /// @dev Get the natural logarithm of a fixed-point number 0 < `x` <= LN_MAX_VAL + /// @notice Get the natural logarithm of a fixed-point number 0 < `x` <= LN_MAX_VAL + /// @param x Fixed-point number to compute logarithm of + /// @return r The natural logarithm of x function ln(int256 x) internal pure returns (int256 r) { if (x > LN_MAX_VAL) { revert("out-of-bounds"); @@ -228,7 +272,9 @@ library LibFixedMath { r += (z * (0x088888888888888888888888888888888 - y)) / 0x800000000000000000000000000000000; // add y^15 / 15 - y^16 / 16 } - /// @dev Compute the natural exponent for a fixed-point number EXP_MIN_VAL <= `x` <= 1 + /// @notice Compute the natural exponent for a fixed-point number EXP_MIN_VAL <= `x` <= 1 + /// @param x Fixed-point number to compute exponent of + /// @return r The natural exponent of x function exp(int256 x) internal pure returns (int256 r) { if (x < EXP_MIN_VAL) { // Saturate to zero below EXP_MIN_VAL. @@ -350,7 +396,10 @@ library LibFixedMath { } } - /// @dev Returns the multiplication two numbers, reverting on overflow. + /// @notice Returns the multiplication two numbers, reverting on overflow. + /// @param a First operand + /// @param b Second operand + /// @return c The product of a and b function _mul(int256 a, int256 b) private pure returns (int256 c) { if (a == 0 || b == 0) { return 0; @@ -361,7 +410,10 @@ library LibFixedMath { } } - /// @dev Returns the division of two numbers, reverting on division by zero. + /// @notice Returns the division of two numbers, reverting on division by zero. + /// @param a Dividend + /// @param b Divisor + /// @return c The quotient of a and b function _div(int256 a, int256 b) private pure returns (int256 c) { if (b == 0) { revert("overflow"); @@ -372,7 +424,10 @@ library LibFixedMath { c = a / b; } - /// @dev Adds two numbers, reverting on overflow. + /// @notice Adds two numbers, reverting on overflow. + /// @param a First operand + /// @param b Second operand + /// @return c The sum of a and b function _add(int256 a, int256 b) private pure returns (int256 c) { c = a + b; if ((a < 0 && b < 0 && c > a) || (a > 0 && b > 0 && c < a)) { diff --git a/packages/contracts/contracts/staking/libs/MathUtils.sol b/packages/contracts/contracts/staking/libs/MathUtils.sol index 0fb20389a..467e1ae2a 100644 --- a/packages/contracts/contracts/staking/libs/MathUtils.sol +++ b/packages/contracts/contracts/staking/libs/MathUtils.sol @@ -2,17 +2,21 @@ pragma solidity ^0.7.6; -import "@openzeppelin/contracts/math/SafeMath.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities + +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; /** * @title MathUtils Library + * @author Edge & Node * @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 + * @notice 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. @@ -20,6 +24,7 @@ library MathUtils { * @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 + * @return The weighted average of the two values, rounded up */ function weightedAverageRoundingUp( uint256 valueA, @@ -31,14 +36,20 @@ library MathUtils { } /** - * @dev Returns the minimum of two numbers. + * @notice Returns the minimum of two numbers. + * @param x First number + * @param y Second number + * @return The smaller of the 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. + * @notice Returns the difference between two numbers or zero if negative. + * @param x First number + * @param y Second number + * @return The difference x - y, or 0 if y > x */ function diffOrZero(uint256 x, uint256 y) internal pure returns (uint256) { return (x > y) ? x.sub(y) : 0; diff --git a/packages/contracts/contracts/staking/libs/Stakes.sol b/packages/contracts/contracts/staking/libs/Stakes.sol index b09101032..459a82996 100644 --- a/packages/contracts/contracts/staking/libs/Stakes.sol +++ b/packages/contracts/contracts/staking/libs/Stakes.sol @@ -3,13 +3,15 @@ pragma solidity ^0.7.6; pragma abicoder v2; -import "@openzeppelin/contracts/math/SafeMath.sol"; +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; -import "./MathUtils.sol"; -import "./IStakes.sol"; +import { MathUtils } from "./MathUtils.sol"; +import { IStakes } from "@graphprotocol/interfaces/contracts/contracts/staking/libs/IStakes.sol"; /** * @title A collection of data structures and functions to manage the Indexer Stake state. + * @author Edge & Node + * @notice A collection of data structures and functions to manage the Indexer Stake state. * Used for low-level state changes, require() conditions should be evaluated * at the caller function scope. */ @@ -18,7 +20,7 @@ library Stakes { using Stakes for IStakes.Indexer; /** - * @dev Deposit tokens to the indexer stake. + * @notice Deposit tokens to the indexer stake. * @param stake Stake data * @param _tokens Amount of tokens to deposit */ @@ -27,7 +29,7 @@ library Stakes { } /** - * @dev Release tokens from the indexer stake. + * @notice Release tokens from the indexer stake. * @param stake Stake data * @param _tokens Amount of tokens to release */ @@ -36,7 +38,7 @@ library Stakes { } /** - * @dev Allocate tokens from the main stack to a SubgraphDeployment. + * @notice Allocate tokens from the main stack to a SubgraphDeployment. * @param stake Stake data * @param _tokens Amount of tokens to allocate */ @@ -45,7 +47,7 @@ library Stakes { } /** - * @dev Unallocate tokens from a SubgraphDeployment back to the main stack. + * @notice Unallocate tokens from a SubgraphDeployment back to the main stack. * @param stake Stake data * @param _tokens Amount of tokens to unallocate */ @@ -54,7 +56,7 @@ library Stakes { } /** - * @dev Lock tokens until a thawing period pass. + * @notice Lock tokens until a thawing period pass. * @param stake Stake data * @param _tokens Amount of tokens to unstake * @param _period Period in blocks that need to pass before withdrawal @@ -77,7 +79,7 @@ library Stakes { } /** - * @dev Unlock tokens. + * @notice Unlock tokens. * @param stake Stake data * @param _tokens Amount of tokens to unlock */ @@ -89,7 +91,7 @@ library Stakes { } /** - * @dev Take all tokens out from the locked stake for withdrawal. + * @notice Take all tokens out from the locked stake for withdrawal. * @param stake Stake data * @return Amount of tokens being withdrawn */ @@ -109,7 +111,7 @@ library Stakes { } /** - * @dev Return the amount of tokens used in allocations and locked for withdrawal. + * @notice Return the amount of tokens used in allocations and locked for withdrawal. * @param stake Stake data * @return Token amount */ @@ -118,7 +120,7 @@ library Stakes { } /** - * @dev Return the amount of tokens staked not considering the ones that are already going + * @notice Return the amount of tokens staked not considering the ones that are already going * through the thawing period or are ready for withdrawal. We call it secure stake because * it is not subject to change by a withdraw call from the indexer. * @param stake Stake data @@ -129,7 +131,7 @@ library Stakes { } /** - * @dev Tokens free balance on the indexer stake that can be used for any purpose. + * @notice Tokens free balance on the indexer stake that can be used for any purpose. * Any token that is allocated cannot be used as well as tokens that are going through the * thawing period or are withdrawable * Calc: tokensStaked - tokensAllocated - tokensLocked @@ -141,7 +143,7 @@ library Stakes { } /** - * @dev Tokens free balance on the indexer stake that can be used for allocations. + * @notice Tokens free balance on the indexer stake that can be used for allocations. * This function accepts a parameter for extra delegated capacity that takes into * account delegated tokens * @param stake Stake data @@ -171,7 +173,7 @@ library Stakes { } /** - * @dev Tokens available for withdrawal after thawing period. + * @notice Tokens available for withdrawal after thawing period. * @param stake Stake data * @return Token amount */ diff --git a/packages/contracts/contracts/tests/CallhookReceiverMock.sol b/packages/contracts/contracts/tests/CallhookReceiverMock.sol index e2418f3c8..f6b9d130e 100644 --- a/packages/contracts/contracts/tests/CallhookReceiverMock.sol +++ b/packages/contracts/contracts/tests/CallhookReceiverMock.sol @@ -2,21 +2,29 @@ pragma solidity ^0.7.6; -import "../gateway/ICallhookReceiver.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events, use-natspec + +import { ICallhookReceiver } from "@graphprotocol/interfaces/contracts/contracts/gateway/ICallhookReceiver.sol"; /** - * @title GovernedMock contract + * @title CallhookReceiverMock contract + * @dev Mock contract for testing callhook receiver functionality */ contract CallhookReceiverMock is ICallhookReceiver { + /** + * @dev Emitted when a transfer is received + * @param from Address that sent the transfer + * @param amount Amount of tokens transferred + * @param foo First test parameter + * @param bar Second test parameter + */ event TransferReceived(address from, uint256 amount, uint256 foo, uint256 bar); /** - * @dev Receive tokens with a callhook from the bridge - * Expects two uint256 values encoded in _data. + * @inheritdoc ICallhookReceiver + * @dev Expects two uint256 values encoded in _data. * Reverts if the first of these values is zero. - * @param _from Token sender in L1 - * @param _amount Amount of tokens that were transferred - * @param _data ABI-encoded callhook data */ function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override { uint256 foo; diff --git a/packages/contracts/contracts/tests/GovernedMock.sol b/packages/contracts/contracts/tests/GovernedMock.sol index cc908287b..9e6c2cc18 100644 --- a/packages/contracts/contracts/tests/GovernedMock.sol +++ b/packages/contracts/contracts/tests/GovernedMock.sol @@ -2,12 +2,19 @@ pragma solidity ^0.7.6; -import "../governance/Governed.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + +import { Governed } from "../governance/Governed.sol"; /** * @title GovernedMock contract + * @dev Mock contract for testing Governed functionality */ contract GovernedMock is Governed { + /** + * @dev Constructor that initializes the contract with the deployer as governor + */ constructor() { Governed._initialize(msg.sender); } diff --git a/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolBadMock.sol b/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolBadMock.sol index f540b1b96..12b06b332 100644 --- a/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolBadMock.sol +++ b/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolBadMock.sol @@ -3,17 +3,37 @@ pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; +// solhint-disable named-parameters-mapping +// solhint-disable gas-small-strings + +/** + * @title L1GraphTokenLockTransferToolBadMock + * @author Edge & Node + * @notice Mock contract for testing L1 Graph Token Lock Transfer Tool with bad behavior + */ contract L1GraphTokenLockTransferToolBadMock { + /** + * @notice Mapping from L1 wallet address to L2 wallet address + */ mapping(address => address) public l2WalletAddress; - function setL2WalletAddress(address _l1Address, address _l2Address) external { - l2WalletAddress[_l1Address] = _l2Address; + /** + * @notice Set the L2 wallet address for an L1 wallet + * @param l1Address L1 wallet address + * @param l2Address L2 wallet address + */ + function setL2WalletAddress(address l1Address, address l2Address) external { + l2WalletAddress[l1Address] = l2Address; } - // Sends 1 wei less than requested - function pullETH(address _l1Wallet, uint256 _amount) external { - require(l2WalletAddress[_l1Wallet] != address(0), "L1GraphTokenLockTransferToolMock: unknown L1 wallet"); - (bool success, ) = payable(msg.sender).call{ value: _amount - 1 }(""); + /** + * @notice Pull ETH from the contract to the caller (sends 1 wei less than requested for testing) + * @param l1Wallet L1 wallet address to check + * @param amount Amount of ETH to pull + */ + function pullETH(address l1Wallet, uint256 amount) external { + require(l2WalletAddress[l1Wallet] != address(0), "L1GraphTokenLockTransferToolMock: unknown L1 wallet"); + (bool success, ) = payable(msg.sender).call{ value: amount - 1 }(""); require(success, "L1GraphTokenLockTransferToolMock: ETH pull failed"); } } diff --git a/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolMock.sol b/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolMock.sol index a1321d62f..92e8f73f7 100644 --- a/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolMock.sol +++ b/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolMock.sol @@ -3,16 +3,37 @@ pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; +// solhint-disable named-parameters-mapping +// solhint-disable gas-small-strings + +/** + * @title L1GraphTokenLockTransferToolMock + * @author Edge & Node + * @notice Mock contract for testing L1 Graph Token Lock Transfer Tool functionality + */ contract L1GraphTokenLockTransferToolMock { + /** + * @notice Mapping from L1 wallet address to L2 wallet address + */ mapping(address => address) public l2WalletAddress; - function setL2WalletAddress(address _l1Address, address _l2Address) external { - l2WalletAddress[_l1Address] = _l2Address; + /** + * @notice Set the L2 wallet address for an L1 wallet + * @param l1Address L1 wallet address + * @param l2Address L2 wallet address + */ + function setL2WalletAddress(address l1Address, address l2Address) external { + l2WalletAddress[l1Address] = l2Address; } - function pullETH(address _l1Wallet, uint256 _amount) external { - require(l2WalletAddress[_l1Wallet] != address(0), "L1GraphTokenLockTransferToolMock: unknown L1 wallet"); - (bool success, ) = payable(msg.sender).call{ value: _amount }(""); + /** + * @notice Pull ETH from the contract to the caller + * @param l1Wallet L1 wallet address to check + * @param amount Amount of ETH to pull + */ + function pullETH(address l1Wallet, uint256 amount) external { + require(l2WalletAddress[l1Wallet] != address(0), "L1GraphTokenLockTransferToolMock: unknown L1 wallet"); + (bool success, ) = payable(msg.sender).call{ value: amount }(""); require(success, "L1GraphTokenLockTransferToolMock: ETH pull failed"); } } diff --git a/packages/contracts/contracts/tests/LegacyGNSMock.sol b/packages/contracts/contracts/tests/LegacyGNSMock.sol index b2b4088b9..30f98ea31 100644 --- a/packages/contracts/contracts/tests/LegacyGNSMock.sol +++ b/packages/contracts/contracts/tests/LegacyGNSMock.sol @@ -3,8 +3,11 @@ pragma solidity ^0.7.6; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + import { L1GNS } from "../discovery/L1GNS.sol"; -import { IGNS } from "../discovery/IGNS.sol"; +import { IGNS } from "@graphprotocol/interfaces/contracts/contracts/discovery/IGNS.sol"; /** * @title LegacyGNSMock contract diff --git a/packages/contracts/contracts/tests/arbitrum/ArbSysMock.sol b/packages/contracts/contracts/tests/arbitrum/ArbSysMock.sol index b5af6114e..3c256fa74 100644 --- a/packages/contracts/contracts/tests/arbitrum/ArbSysMock.sol +++ b/packages/contracts/contracts/tests/arbitrum/ArbSysMock.sol @@ -2,12 +2,22 @@ pragma solidity ^0.7.6; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + /** * @title ArbSys Mock Contract * @dev This is a mock implementation of the ArbSys precompiled contract used in Arbitrum * It's used for testing the L2GraphTokenGateway contract */ contract ArbSysMock { + /** + * @dev Emitted when a transaction is sent from L2 to L1 + * @param from Address sending the transaction on L2 + * @param to Address receiving the transaction on L1 + * @param id Unique identifier for the L2-to-L1 transaction + * @param data Transaction data + */ event L2ToL1Tx(address indexed from, address indexed to, uint256 indexed id, bytes data); /** diff --git a/packages/contracts/contracts/tests/arbitrum/BridgeMock.sol b/packages/contracts/contracts/tests/arbitrum/BridgeMock.sol index 77be89b4e..9bcc71982 100644 --- a/packages/contracts/contracts/tests/arbitrum/BridgeMock.sol +++ b/packages/contracts/contracts/tests/arbitrum/BridgeMock.sol @@ -2,29 +2,35 @@ pragma solidity ^0.7.6; -import "../../arbitrum/IBridge.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-increment-by-one, use-natspec + +import { IBridge } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/IBridge.sol"; /** * @title Arbitrum Bridge mock contract * @dev This contract implements Arbitrum's IBridge interface for testing purposes */ contract BridgeMock is IBridge { - // Address of the (mock) Arbitrum Inbox + /** + * @notice Address of the (mock) Arbitrum Inbox + */ address public inbox; - // Address of the (mock) Arbitrum Outbox + /** + * @notice Address of the (mock) Arbitrum Outbox + */ address public outbox; - // Index of the next message on the inbox messages array + /** + * @notice Index of the next message on the inbox messages array + */ uint256 public messageIndex; - // Inbox messages array + /** + * @inheritdoc IBridge + */ bytes32[] public override inboxAccs; /** - * @dev Deliver a message to the inbox. The encoded message will be - * added to the inbox array, and messageIndex will be incremented. - * @param _kind Type of the message - * @param _sender Address that is sending the message - * @param _messageDataHash keccak256 hash of the message data - * @return The next index for the inbox array + * @inheritdoc IBridge */ function deliverMessageToInbox( uint8 _kind, @@ -38,13 +44,7 @@ contract BridgeMock is IBridge { } /** - * @dev Executes an L1 function call incoing from L2. This can only be called - * by the Outbox. - * @param _destAddr Contract to call - * @param _amount ETH value to send - * @param _data Calldata for the function call - * @return True if the call was successful, false otherwise - * @return Return data from the call + * @inheritdoc IBridge */ function executeCall( address _destAddr, @@ -62,9 +62,7 @@ contract BridgeMock is IBridge { } /** - * @dev Set the address of the inbox. Anyone can call this, because it's a mock. - * @param _inbox Address of the inbox - * @param _enabled Enable the inbox (ignored) + * @inheritdoc IBridge */ function setInbox(address _inbox, bool _enabled) external override { inbox = _inbox; @@ -72,9 +70,7 @@ contract BridgeMock is IBridge { } /** - * @dev Set the address of the outbox. Anyone can call this, because it's a mock. - * @param _outbox Address of the outbox - * @param _enabled Enable the outbox (ignored) + * @inheritdoc IBridge */ function setOutbox(address _outbox, bool _enabled) external override { outbox = _outbox; @@ -84,33 +80,28 @@ contract BridgeMock is IBridge { // View functions /** - * @dev Getter for the active outbox (in this case there's only one) + * @inheritdoc IBridge */ function activeOutbox() external view override returns (address) { return outbox; } /** - * @dev Getter for whether an address is an allowed inbox (in this case there's only one) - * @param _inbox Address to check - * @return True if the address is the allowed inbox, false otherwise + * @inheritdoc IBridge */ function allowedInboxes(address _inbox) external view override returns (bool) { return _inbox == inbox; } /** - * @dev Getter for whether an address is an allowed outbox (in this case there's only one) - * @param _outbox Address to check - * @return True if the address is the allowed outbox, false otherwise + * @inheritdoc IBridge */ function allowedOutboxes(address _outbox) external view override returns (bool) { return _outbox == outbox; } /** - * @dev Getter for the count of messages in the inboxAccs - * @return Number of messages in inboxAccs + * @inheritdoc IBridge */ function messageCount() external view override returns (uint256) { return inboxAccs.length; diff --git a/packages/contracts/contracts/tests/arbitrum/InboxMock.sol b/packages/contracts/contracts/tests/arbitrum/InboxMock.sol index 57af6941c..38cee3b44 100644 --- a/packages/contracts/contracts/tests/arbitrum/InboxMock.sol +++ b/packages/contracts/contracts/tests/arbitrum/InboxMock.sol @@ -2,26 +2,28 @@ pragma solidity ^0.7.6; -import "../../arbitrum/IInbox.sol"; -import "../../arbitrum/AddressAliasHelper.sol"; +import { IInbox } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/IInbox.sol"; +import { AddressAliasHelper } from "../../arbitrum/AddressAliasHelper.sol"; +import { IBridge } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/IBridge.sol"; /** * @title Arbitrum Inbox mock contract - * @dev This contract implements (a subset of) Arbitrum's IInbox interface for testing purposes + * @author Edge & Node + * @notice This contract implements (a subset of) Arbitrum's IInbox interface for testing purposes */ contract InboxMock is IInbox { - // Type indicator for a standard L2 message + /// @dev Type indicator for a standard L2 message uint8 internal constant L2_MSG = 3; - // Type indicator for a retryable ticket message + /// @dev Type indicator for a retryable ticket message // solhint-disable-next-line const-name-snakecase uint8 internal constant L1MessageType_submitRetryableTx = 9; - // Address of the Bridge (mock) contract + /** + * @inheritdoc IInbox + */ IBridge public override bridge; /** - * @dev Send a message to L2 (by delivering it to the Bridge) - * @param _messageData Encoded data to send in the message - * @return message number returned by the inbox + * @inheritdoc IInbox */ function sendL2Message(bytes calldata _messageData) external override returns (uint256) { uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(_messageData)); @@ -30,7 +32,7 @@ contract InboxMock is IInbox { } /** - * @dev Set the address of the (mock) bridge + * @notice Set the address of the (mock) bridge * @param _bridge Address of the bridge */ function setBridge(address _bridge) external { @@ -38,6 +40,7 @@ contract InboxMock is IInbox { } /** + * @inheritdoc IInbox * @dev Unimplemented in this mock */ function sendUnsignedTransaction( @@ -52,6 +55,7 @@ contract InboxMock is IInbox { } /** + * @inheritdoc IInbox * @dev Unimplemented in this mock */ function sendContractTransaction( @@ -65,6 +69,7 @@ contract InboxMock is IInbox { } /** + * @inheritdoc IInbox * @dev Unimplemented in this mock */ function sendL1FundedUnsignedTransaction( @@ -78,6 +83,7 @@ contract InboxMock is IInbox { } /** + * @inheritdoc IInbox * @dev Unimplemented in this mock */ function sendL1FundedContractTransaction( @@ -90,16 +96,7 @@ contract InboxMock is IInbox { } /** - * @dev Creates a retryable ticket for an L2 transaction - * @param _destAddr Address of the contract to call in L2 - * @param _arbTxCallValue Callvalue to use in the L2 transaction - * @param _maxSubmissionCost Max cost of submitting the ticket, in Wei - * @param _submissionRefundAddress L2 address to refund for any remaining value from the submission cost - * @param _valueRefundAddress L2 address to refund if the ticket times out or gets cancelled - * @param _maxGas Max gas for the L2 transcation - * @param _gasPriceBid Gas price bid on L2 - * @param _data Encoded calldata for the L2 transaction (including function selector) - * @return message number returned by the bridge + * @inheritdoc IInbox */ function createRetryableTicket( address _destAddr, @@ -132,11 +129,16 @@ contract InboxMock is IInbox { ); } + /** + * @inheritdoc IInbox + * @dev Unimplemented in this mock + */ function depositEth(uint256) external payable override returns (uint256) { revert("Unimplemented"); } /** + * @inheritdoc IInbox * @dev Unimplemented in this mock */ function pauseCreateRetryables() external pure override { @@ -144,6 +146,7 @@ contract InboxMock is IInbox { } /** + * @inheritdoc IInbox * @dev Unimplemented in this mock */ function unpauseCreateRetryables() external pure override { @@ -151,6 +154,7 @@ contract InboxMock is IInbox { } /** + * @inheritdoc IInbox * @dev Unimplemented in this mock */ function startRewriteAddress() external pure override { @@ -158,6 +162,7 @@ contract InboxMock is IInbox { } /** + * @inheritdoc IInbox * @dev Unimplemented in this mock */ function stopRewriteAddress() external pure override { @@ -165,7 +170,7 @@ contract InboxMock is IInbox { } /** - * @dev Deliver a message to the bridge + * @notice Deliver a message to the bridge * @param _kind Type of the message * @param _sender Address that is sending the message * @param _messageData Encoded message data @@ -178,7 +183,7 @@ contract InboxMock is IInbox { } /** - * @dev Deliver a message to the bridge + * @notice Deliver a message to the bridge * @param _kind Type of the message * @param _sender Address that is sending the message * @param _messageDataHash keccak256 hash of the encoded message data diff --git a/packages/contracts/contracts/tests/arbitrum/OutboxMock.sol b/packages/contracts/contracts/tests/arbitrum/OutboxMock.sol index 92b9bb246..7a8e9932b 100644 --- a/packages/contracts/contracts/tests/arbitrum/OutboxMock.sol +++ b/packages/contracts/contracts/tests/arbitrum/OutboxMock.sol @@ -2,15 +2,26 @@ pragma solidity ^0.7.6; -import "../../arbitrum/IOutbox.sol"; -import "../../arbitrum/IBridge.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + +import { IOutbox } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/IOutbox.sol"; +import { IBridge } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/IBridge.sol"; /** * @title Arbitrum Outbox mock contract * @dev This contract implements (a subset of) Arbitrum's IOutbox interface for testing purposes */ contract OutboxMock is IOutbox { - // Context of an L2-to-L1 function call + /** + * @dev Context of an L2-to-L1 function call + * @param l2Block L2 block number + * @param l1Block L1 block number + * @param timestamp Timestamp of the call + * @param batchNum Batch number + * @param outputId Output ID + * @param sender Address of the sender + */ struct L2ToL1Context { uint128 l2Block; uint128 l1Block; @@ -19,7 +30,7 @@ contract OutboxMock is IOutbox { bytes32 outputId; address sender; } - // Context of the current L2-to-L1 function call (set and cleared in each transaction) + /// @dev Context of the current L2-to-L1 function call (set and cleared in each transaction) L2ToL1Context internal context; // Address of the (mock) Arbitrum Bridge @@ -33,59 +44,42 @@ contract OutboxMock is IOutbox { bridge = IBridge(_bridge); } - /** - * @dev Getter for the L2 sender of the current incoming message - */ + /// @inheritdoc IOutbox function l2ToL1Sender() external view override returns (address) { return context.sender; } - /** - * @dev Getter for the L2 block of the current incoming message - */ + /// @inheritdoc IOutbox function l2ToL1Block() external view override returns (uint256) { return context.l2Block; } - /** - * @dev Getter for the L1 block of the current incoming message - */ + /// @inheritdoc IOutbox function l2ToL1EthBlock() external view override returns (uint256) { return context.l1Block; } - /** - * @dev Getter for the L1 timestamp of the current incoming message - */ + /// @inheritdoc IOutbox function l2ToL1Timestamp() external view override returns (uint256) { return context.timestamp; } - /** - * @dev Getter for the L2 batch number of the current incoming message - */ + /// @inheritdoc IOutbox function l2ToL1BatchNum() external view override returns (uint256) { return context.batchNum; } - /** - * @dev Getter for the output ID of the current incoming message - */ + /// @inheritdoc IOutbox function l2ToL1OutputId() external view override returns (bytes32) { return context.outputId; } - /** - * @dev Unimplemented in this mock - */ + /// @inheritdoc IOutbox function processOutgoingMessages(bytes calldata, uint256[] calldata) external pure override { revert("Unimplemented"); } - /** - * @dev Check whether an outbox entry for a message exists. - * This mock returns always true. - */ + /// @inheritdoc IOutbox function outboxEntryExists(uint256) external pure override returns (bool) { return true; } diff --git a/packages/contracts/contracts/tests/ens/IENS.sol b/packages/contracts/contracts/tests/ens/IENS.sol index f03cb651c..042a9170f 100644 --- a/packages/contracts/contracts/tests/ens/IENS.sol +++ b/packages/contracts/contracts/tests/ens/IENS.sol @@ -1,9 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.7.6; // Needed for abi and typechain in the npm package +/** + * @title ENS Registry Interface + * @author Edge & Node + * @notice Interface for the Ethereum Name Service registry + */ interface IENS { + /** + * @notice Get the owner of a node + * @param node The node to query + * @return The address of the owner + */ function owner(bytes32 node) external view returns (address); - // Must call setRecord, not setOwner, We must namehash it ourselves as well - function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external; + /** + * @notice Set the record for a subnode + * @dev Must call setRecord, not setOwner. We must namehash it ourselves as well. + * @param node The parent node + * @param label The label hash of the subnode + * @param _owner The address of the new owner + * @param resolver The address of the resolver + * @param ttl The TTL in seconds + */ + function setSubnodeRecord(bytes32 node, bytes32 label, address _owner, address resolver, uint64 ttl) external; } diff --git a/packages/contracts/contracts/tests/ens/IPublicResolver.sol b/packages/contracts/contracts/tests/ens/IPublicResolver.sol index 06ce2243b..7a449fb8d 100644 --- a/packages/contracts/contracts/tests/ens/IPublicResolver.sol +++ b/packages/contracts/contracts/tests/ens/IPublicResolver.sol @@ -1,8 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.7.6; // Needed for abi and typechain in the npm package +/** + * @title ENS Public Resolver Interface + * @author Edge & Node + * @notice Interface for the ENS public resolver contract + */ interface IPublicResolver { + /** + * @notice Get the text record for a node + * @param node The node to query + * @param key The key of the text record + * @return The text record value + */ function text(bytes32 node, string calldata key) external view returns (string memory); + /** + * @notice Set the text record for a node + * @param node The node to set the record for + * @param key The key of the text record + * @param value The value to set + */ function setText(bytes32 node, string calldata key, string calldata value) external; } diff --git a/packages/contracts/contracts/tests/ens/ITestRegistrar.sol b/packages/contracts/contracts/tests/ens/ITestRegistrar.sol index 8a795cc85..406a27fb7 100644 --- a/packages/contracts/contracts/tests/ens/ITestRegistrar.sol +++ b/packages/contracts/contracts/tests/ens/ITestRegistrar.sol @@ -1,5 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.7.6; +/** + * @title Test Registrar Interface + * @author Edge & Node + * @notice Interface for a test ENS registrar contract + */ interface ITestRegistrar { + /** + * @notice Register a name with the registrar + * @param label The label hash to register + * @param owner The address to assign ownership to + */ function register(bytes32 label, address owner) external; } diff --git a/packages/contracts/contracts/token/GraphToken.sol b/packages/contracts/contracts/token/GraphToken.sol index 53496b9a5..652fa5477 100644 --- a/packages/contracts/contracts/token/GraphToken.sol +++ b/packages/contracts/contracts/token/GraphToken.sol @@ -2,16 +2,21 @@ pragma solidity ^0.7.6; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol"; -import "@openzeppelin/contracts/cryptography/ECDSA.sol"; -import "@openzeppelin/contracts/math/SafeMath.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-small-strings, gas-strict-inequalities +// solhint-disable named-parameters-mapping -import "../governance/Governed.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ERC20Burnable } from "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol"; +import { ECDSA } from "@openzeppelin/contracts/cryptography/ECDSA.sol"; +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; + +import { Governed } from "../governance/Governed.sol"; /** * @title GraphToken contract - * @dev This is the implementation of the ERC20 Graph Token. + * @author Edge & Node + * @notice This is the implementation of the ERC20 Graph Token. * The implementation exposes a Permit() function to allow for a spender to send a signed message * and approve funds to a spender following EIP2612 to make integration with other contracts easier. * @@ -28,32 +33,53 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { // -- EIP712 -- // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#definition-of-domainseparator + /// @dev EIP-712 domain type hash for signature verification bytes32 private constant DOMAIN_TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)"); + /// @dev EIP-712 domain name hash for signature verification bytes32 private constant DOMAIN_NAME_HASH = keccak256("Graph Token"); + /// @dev EIP-712 domain version hash for signature verification bytes32 private constant DOMAIN_VERSION_HASH = keccak256("0"); + /// @dev EIP-712 domain salt for signature verification (randomly generated) bytes32 private constant DOMAIN_SALT = 0x51f3d585afe6dfeb2af01bba0889a36c1db03beec88c6a4d0c53817069026afa; // Randomly generated salt + /// @dev EIP-712 permit typehash for signature verification bytes32 private constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); // -- State -- - bytes32 private DOMAIN_SEPARATOR; + /// @dev EIP-712 domain separator for signature verification + bytes32 private domainSeparator; + /// @dev Mapping of addresses authorized to mint tokens mapping(address => bool) private _minters; + /** + * @notice Nonces for permit functionality (EIP-2612) + * @dev Mapping from owner address to current nonce for permit signatures + */ mapping(address => uint256) public nonces; // -- Events -- + /** + * @notice Emitted when a new minter is added + * @param account Address of the minter that was added + */ event MinterAdded(address indexed account); + + /** + * @notice Emitted when a minter is removed + * @param account Address of the minter that was removed + */ event MinterRemoved(address indexed account); + /// @dev Modifier to restrict access to minters only modifier onlyMinter() { require(isMinter(msg.sender), "Only minter can call"); _; } /** - * @dev Graph Token Contract Constructor. + * @notice Graph Token Contract Constructor. * @param _initialSupply Initial supply of GRT */ constructor(uint256 _initialSupply) ERC20("Graph Token", "GRT") { @@ -66,7 +92,7 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { _addMinter(msg.sender); // EIP-712 domain separator - DOMAIN_SEPARATOR = keccak256( + domainSeparator = keccak256( abi.encode( DOMAIN_TYPE_HASH, DOMAIN_NAME_HASH, @@ -79,7 +105,7 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { } /** - * @dev Approve token allowance by validating a message signed by the holder. + * @notice Approve token allowance by validating a message signed by the holder. * @param _owner Address of the token holder * @param _spender Address of the approved spender * @param _value Amount of tokens to approve the spender @@ -100,7 +126,7 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { bytes32 digest = keccak256( abi.encodePacked( "\x19\x01", - DOMAIN_SEPARATOR, + domainSeparator, keccak256(abi.encode(PERMIT_TYPEHASH, _owner, _spender, _value, nonces[_owner], _deadline)) ) ); @@ -114,7 +140,7 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { } /** - * @dev Add a new minter. + * @notice Add a new minter. * @param _account Address of the minter */ function addMinter(address _account) external onlyGovernor { @@ -122,7 +148,7 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { } /** - * @dev Remove a minter. + * @notice Remove a minter. * @param _account Address of the minter */ function removeMinter(address _account) external onlyGovernor { @@ -130,14 +156,14 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { } /** - * @dev Renounce to be a minter. + * @notice Renounce to be a minter. */ function renounceMinter() external { _removeMinter(msg.sender); } /** - * @dev Mint new tokens. + * @notice Mint new tokens. * @param _to Address to send the newly minted tokens * @param _amount Amount of tokens to mint */ @@ -146,7 +172,7 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { } /** - * @dev Return if the `_account` is a minter or not. + * @notice Return if the `_account` is a minter or not. * @param _account Address to check * @return True if the `_account` is minter */ @@ -155,7 +181,7 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { } /** - * @dev Add a new minter. + * @notice Add a new minter. * @param _account Address of the minter */ function _addMinter(address _account) private { @@ -164,7 +190,7 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { } /** - * @dev Remove a minter. + * @notice Remove a minter. * @param _account Address of the minter */ function _removeMinter(address _account) private { @@ -173,11 +199,12 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { } /** - * @dev Get the running network chain ID. + * @notice Get the running network chain ID. * @return The chain ID */ function _getChainID() private pure returns (uint256) { uint256 id; + // solhint-disable-next-line no-inline-assembly assembly { id := chainid() } diff --git a/packages/contracts/contracts/token/IGraphToken.sol b/packages/contracts/contracts/token/IGraphToken.sol deleted file mode 100644 index df3b7643f..000000000 --- a/packages/contracts/contracts/token/IGraphToken.sol +++ /dev/null @@ -1,43 +0,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); -} diff --git a/packages/contracts/contracts/upgrades/GraphProxy.sol b/packages/contracts/contracts/upgrades/GraphProxy.sol index d6fbfac7f..b787b476a 100644 --- a/packages/contracts/contracts/upgrades/GraphProxy.sol +++ b/packages/contracts/contracts/upgrades/GraphProxy.sol @@ -2,13 +2,19 @@ pragma solidity ^0.7.6 || 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-small-strings + +/* solhint-disable gas-custom-errors */ // Cannot use custom errors with 0.7.6 + import { GraphProxyStorage } from "./GraphProxyStorage.sol"; -import { IGraphProxy } from "./IGraphProxy.sol"; +import { IGraphProxy } from "@graphprotocol/interfaces/contracts/contracts/upgrades/IGraphProxy.sol"; /** * @title Graph Proxy - * @dev Graph Proxy contract used to delegate call implementation contracts and support upgrades. + * @author Edge & Node + * @notice Graph Proxy contract used to delegate call implementation contracts and support upgrades. * This contract should NOT define storage as it is managed by GraphProxyStorage. * This contract implements a proxy that is upgradeable by an admin. * https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies#transparent-proxies-and-function-clashes @@ -69,56 +75,49 @@ contract GraphProxy is GraphProxyStorage, IGraphProxy { } /** - * @notice Get the current admin - * + * @inheritdoc IGraphProxy * @dev NOTE: Only the admin and implementation can call this function. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` - * - * @return The address of the current admin */ - function admin() external override ifAdminOrPendingImpl returns (address) { + function admin() external override ifAdminOrPendingImpl returns (address adminAddress) { return _getAdmin(); } /** - * @notice Get the current implementation. - * + * @inheritdoc IGraphProxy * @dev NOTE: Only the admin can call this function. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` - * - * @return The address of the current implementation for this proxy */ - function implementation() external override ifAdminOrPendingImpl returns (address) { + function implementation() external override ifAdminOrPendingImpl returns (address implementationAddress) { return _getImplementation(); } /** - * @notice Get the current pending implementation. - * + * @inheritdoc IGraphProxy * @dev NOTE: Only the admin can call this function. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c` - * - * @return The address of the current pending implementation for this proxy */ - function pendingImplementation() external override ifAdminOrPendingImpl returns (address) { + function pendingImplementation() + external + override + ifAdminOrPendingImpl + returns (address pendingImplementationAddress) + { return _getPendingImplementation(); } /** - * @notice Changes the admin of the proxy. - * + * @inheritdoc IGraphProxy * @dev NOTE: Only the admin can call this function. - * - * @param _newAdmin Address of the new admin */ function setAdmin(address _newAdmin) external override ifAdmin { require(_newAdmin != address(0), "Admin cant be the zero address"); @@ -126,25 +125,22 @@ contract GraphProxy is GraphProxyStorage, IGraphProxy { } /** - * @notice Upgrades to a new implementation contract. + * @inheritdoc IGraphProxy * @dev NOTE: Only the admin can call this function. - * @param _newImplementation Address of implementation contract */ function upgradeTo(address _newImplementation) external override ifAdmin { _setPendingImplementation(_newImplementation); } /** - * @notice Admin function for new implementation to accept its role as implementation. + * @inheritdoc IGraphProxy */ function acceptUpgrade() external override ifAdminOrPendingImpl { _acceptUpgrade(); } /** - * @notice Admin function for new implementation to accept its role as implementation, - * calling a function on the new implementation. - * @param data Calldata (including selector) for the function to delegatecall into the implementation + * @inheritdoc IGraphProxy */ function acceptUpgradeAndCall(bytes calldata data) external override ifAdminOrPendingImpl { _acceptUpgrade(); @@ -154,7 +150,7 @@ contract GraphProxy is GraphProxyStorage, IGraphProxy { } /** - * @dev Admin function for new implementation to accept its role as implementation. + * @notice Admin function for new implementation to accept its role as implementation. */ function _acceptUpgrade() internal { address _pendingImplementation = _getPendingImplementation(); @@ -166,7 +162,7 @@ contract GraphProxy is GraphProxyStorage, IGraphProxy { } /** - * @dev Delegates the current call to implementation. + * @notice Delegates the current call to implementation. * This function does not return to its internal call site, it will return directly to the * external caller. */ diff --git a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol index db8e9dcb3..97f0b2e11 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol @@ -2,14 +2,17 @@ pragma solidity ^0.7.6 || 0.8.27; +/* solhint-disable gas-custom-errors */ // Cannot use custom errors with 0.7.6 + import { Governed } from "../governance/Governed.sol"; -import { IGraphProxy } from "./IGraphProxy.sol"; +import { IGraphProxy } from "@graphprotocol/interfaces/contracts/contracts/upgrades/IGraphProxy.sol"; import { GraphUpgradeable } from "./GraphUpgradeable.sol"; /** * @title GraphProxyAdmin - * @dev This is the owner of upgradeable proxy contracts. + * @author Edge & Node + * @notice This is the owner of upgradeable proxy contracts. * Proxy contracts use a TransparentProxy pattern, any admin related call * like upgrading a contract or changing the admin needs to be send through * this contract. diff --git a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol index 7871e4996..828af8e23 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol @@ -2,9 +2,12 @@ pragma solidity ^0.7.6 || 0.8.27; +/* solhint-disable gas-custom-errors */ // Cannot use custom errors with 0.7.6 + /** * @title Graph Proxy Storage - * @dev Contract functions related to getting and setting proxy storage. + * @author Edge & Node + * @notice Contract functions related to getting and setting proxy storage. * This contract does not actually define state variables managed by the compiler * but uses fixed slot locations. */ @@ -32,7 +35,9 @@ abstract contract GraphProxyStorage { bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** - * @dev Emitted when pendingImplementation is changed. + * @notice Emitted when pendingImplementation is changed. + * @param oldPendingImplementation Address of the previous pending implementation + * @param newPendingImplementation Address of the new pending implementation */ event PendingImplementationUpdated( address indexed oldPendingImplementation, @@ -40,13 +45,17 @@ abstract contract GraphProxyStorage { ); /** - * @dev Emitted when pendingImplementation is accepted, + * @notice Emitted when pendingImplementation is accepted, * which means contract implementation is updated. + * @param oldImplementation Address of the previous implementation + * @param newImplementation Address of the new implementation */ event ImplementationUpdated(address indexed oldImplementation, address indexed newImplementation); /** - * @dev Emitted when the admin account has changed. + * @notice Emitted when the admin account has changed. + * @param oldAdmin Address of the previous admin + * @param newAdmin Address of the new admin */ event AdminUpdated(address indexed oldAdmin, address indexed newAdmin); @@ -59,6 +68,7 @@ abstract contract GraphProxyStorage { } /** + * @notice Returns the current admin address * @return adm The admin slot. */ function _getAdmin() internal view returns (address adm) { @@ -70,7 +80,7 @@ abstract contract GraphProxyStorage { } /** - * @dev Sets the address of the proxy admin. + * @notice Sets the address of the proxy admin. * @param _newAdmin Address of the new proxy admin */ function _setAdmin(address _newAdmin) internal { @@ -85,7 +95,7 @@ abstract contract GraphProxyStorage { } /** - * @dev Returns the current implementation. + * @notice Returns the current implementation. * @return impl Address of the current implementation */ function _getImplementation() internal view returns (address impl) { @@ -97,7 +107,7 @@ abstract contract GraphProxyStorage { } /** - * @dev Returns the current pending implementation. + * @notice Returns the current pending implementation. * @return impl Address of the current pending implementation */ function _getPendingImplementation() internal view returns (address impl) { @@ -109,7 +119,7 @@ abstract contract GraphProxyStorage { } /** - * @dev Sets the implementation address of the proxy. + * @notice Sets the implementation address of the proxy. * @param _newImplementation Address of the new implementation */ function _setImplementation(address _newImplementation) internal { @@ -125,7 +135,7 @@ abstract contract GraphProxyStorage { } /** - * @dev Sets the pending implementation address of the proxy. + * @notice Sets the pending implementation address of the proxy. * @param _newImplementation Address of the new pending implementation */ function _setPendingImplementation(address _newImplementation) internal { diff --git a/packages/contracts/contracts/upgrades/GraphUpgradeable.sol b/packages/contracts/contracts/upgrades/GraphUpgradeable.sol index 60dfbe888..827082213 100644 --- a/packages/contracts/contracts/upgrades/GraphUpgradeable.sol +++ b/packages/contracts/contracts/upgrades/GraphUpgradeable.sol @@ -2,11 +2,14 @@ pragma solidity ^0.7.6 || 0.8.27; -import { IGraphProxy } from "./IGraphProxy.sol"; +/* solhint-disable gas-custom-errors */ // Cannot use custom errors with 0.7.6 + +import { IGraphProxy } from "@graphprotocol/interfaces/contracts/contracts/upgrades/IGraphProxy.sol"; /** * @title Graph Upgradeable - * @dev This contract is intended to be inherited from upgradeable contracts. + * @author Edge & Node + * @notice This contract is intended to be inherited from upgradeable contracts. */ abstract contract GraphUpgradeable { /** @@ -18,6 +21,7 @@ abstract contract GraphUpgradeable { /** * @dev Check if the caller is the proxy admin. + * @param _proxy The proxy contract to check admin for */ modifier onlyProxyAdmin(IGraphProxy _proxy) { require(msg.sender == _proxy.admin(), "Caller must be the proxy admin"); @@ -33,7 +37,7 @@ abstract contract GraphUpgradeable { } /** - * @dev Returns the current implementation. + * @notice Returns the current implementation. * @return impl Address of the current implementation */ function _implementation() internal view returns (address impl) { diff --git a/packages/contracts/contracts/upgrades/IGraphProxy.sol b/packages/contracts/contracts/upgrades/IGraphProxy.sol deleted file mode 100644 index 4f501ed7c..000000000 --- a/packages/contracts/contracts/upgrades/IGraphProxy.sol +++ /dev/null @@ -1,19 +0,0 @@ -// 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; -} diff --git a/packages/contracts/contracts/utils/TokenUtils.sol b/packages/contracts/contracts/utils/TokenUtils.sol index ef2f03211..b1c2290f6 100644 --- a/packages/contracts/contracts/utils/TokenUtils.sol +++ b/packages/contracts/contracts/utils/TokenUtils.sol @@ -2,17 +2,20 @@ pragma solidity ^0.7.6 || 0.8.27; -import { IGraphToken } from "../token/IGraphToken.sol"; +/* solhint-disable gas-custom-errors */ // Cannot use custom errors with 0.7.6 + +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; /** * @title TokenUtils library + * @author Edge & Node * @notice This library contains utility functions for handling tokens (transfers and burns). * It is specifically adapted for the GraphToken, so does not need to handle edge cases * for other tokens. */ library TokenUtils { /** - * @dev Pull tokens from an address to this contract. + * @notice Pull tokens from an address to this contract. * @param _graphToken Token to transfer * @param _from Address sending the tokens * @param _amount Amount of tokens to transfer @@ -24,7 +27,7 @@ library TokenUtils { } /** - * @dev Push tokens from this contract to a receiving address. + * @notice Push tokens from this contract to a receiving address. * @param _graphToken Token to transfer * @param _to Address receiving the tokens * @param _amount Amount of tokens to transfer @@ -36,7 +39,7 @@ library TokenUtils { } /** - * @dev Burn tokens held by this contract. + * @notice Burn tokens held by this contract. * @param _graphToken Token to burn * @param _amount Amount of tokens to burn */ diff --git a/packages/contracts/test/hardhat.config.ts b/packages/contracts/test/hardhat.config.ts index 1d8ed1c58..9555c7c7f 100644 --- a/packages/contracts/test/hardhat.config.ts +++ b/packages/contracts/test/hardhat.config.ts @@ -5,6 +5,7 @@ import '@nomiclabs/hardhat-waffle' import '@typechain/hardhat' import 'dotenv/config' import 'hardhat-gas-reporter' +import 'hardhat-ignore-warnings' import 'solidity-coverage' // Test-specific tasks import './tasks/migrate/nitro' @@ -44,6 +45,18 @@ const config: HardhatUserConfig = { typechain: { outDir: 'types', }, + warnings: { + // Suppress warnings from legacy OpenZeppelin contracts and external dependencies + 'arbos-precompiles/**/*': { + default: 'off', + }, + '@openzeppelin/contracts/**/*': { + default: 'off', + }, + 'contracts/staking/StakingExtension.sol': { + 5667: 'off', // Unused function parameter + }, + }, defaultNetwork: 'hardhat', networks: { hardhat: { diff --git a/packages/data-edge/contracts/DataEdge.sol b/packages/data-edge/contracts/DataEdge.sol index fc39b7386..8b02c3ce0 100644 --- a/packages/data-edge/contracts/DataEdge.sol +++ b/packages/data-edge/contracts/DataEdge.sol @@ -5,8 +5,10 @@ pragma solidity ^0.8.12; /// @title Data Edge contract is only used to store on-chain data, it does not /// perform execution. On-chain client services can read the data /// and decode the payload for different purposes. +/// @author Edge & Node +/// @notice Contract for storing on-chain data without execution contract DataEdge { - /// @dev Fallback function, accepts any payload + /// @notice Fallback function, accepts any payload fallback() external payable { // no-op } diff --git a/packages/data-edge/contracts/EventfulDataEdge.sol b/packages/data-edge/contracts/EventfulDataEdge.sol index d995be665..d3725f151 100644 --- a/packages/data-edge/contracts/EventfulDataEdge.sol +++ b/packages/data-edge/contracts/EventfulDataEdge.sol @@ -6,9 +6,14 @@ pragma solidity ^0.8.12; /// perform execution. On-chain client services can read the data /// and decode the payload for different purposes. /// NOTE: This version emits an event with the calldata. +/// @author Edge & Node +/// @notice Contract for storing on-chain data with event logging contract EventfulDataEdge { + /// @notice Emitted when data is received + /// @param data The calldata received by the contract event Log(bytes data); + /// @notice Accepts any payload and emits it as an event /// @dev Fallback function, accepts any payload fallback() external payable { emit Log(msg.data); diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index 6b14365d5..21205dbfe 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -9,6 +9,7 @@ import { ProvisionManager } from "./utilities/ProvisionManager.sol"; /** * @title DataService contract + * @author Edge & Node * @dev Implementation of the {IDataService} interface. * @notice This implementation provides base functionality for a data service: * - GraphDirectory, allows the data service to interact with Graph Horizon contracts @@ -32,6 +33,7 @@ import { ProvisionManager } from "./utilities/ProvisionManager.sol"; */ abstract contract DataService is GraphDirectory, ProvisionManager, DataServiceV1Storage, IDataService { /** + * @notice Constructor for the DataService contract * @dev Addresses in GraphDirectory are immutables, they can only be set in this constructor. * @param controller The address of the Graph Horizon controller contract. */ diff --git a/packages/horizon/contracts/data-service/DataServiceStorage.sol b/packages/horizon/contracts/data-service/DataServiceStorage.sol index df759b892..0b6d27e4b 100644 --- a/packages/horizon/contracts/data-service/DataServiceStorage.sol +++ b/packages/horizon/contracts/data-service/DataServiceStorage.sol @@ -3,7 +3,8 @@ pragma solidity 0.8.27; /** * @title DataServiceStorage - * @dev This contract holds the storage variables for the DataService contract. + * @author Edge & Node + * @notice This contract holds the storage variables for the DataService contract. * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index a82c15361..91f5c5f4e 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -12,6 +12,7 @@ import { DataServiceFeesV1Storage } from "./DataServiceFeesStorage.sol"; /** * @title DataServiceFees contract + * @author Edge & Node * @dev Implementation of the {IDataServiceFees} interface. * @notice Extension for the {IDataService} contract to handle payment collateralization * using a Horizon provision. See {IDataServiceFees} for more details. diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol index 78d826f03..bafb8fe52 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol @@ -7,6 +7,8 @@ import { ILinkedList } from "@graphprotocol/interfaces/contracts/horizon/interna /** * @title Storage layout for the {DataServiceFees} extension contract. + * @author Edge & Node + * @notice Storage layout for the DataServiceFees extension contract * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol index a4c60f7db..b1bd4203a 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol @@ -8,6 +8,7 @@ import { DataService } from "../DataService.sol"; /** * @title DataServicePausable contract + * @author Edge & Node * @dev Implementation of the {IDataServicePausable} interface. * @notice Extension for the {IDataService} contract, adds pausing functionality * to the data service. Pausing is controlled by privileged accounts called diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol index 2ca8e09c6..ad792f914 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol @@ -8,8 +8,9 @@ import { DataService } from "../DataService.sol"; /** * @title DataServicePausableUpgradeable contract + * @author Edge & Node + * @notice Upgradeable version of the {DataServicePausable} contract. * @dev Implementation of the {IDataServicePausable} interface. - * @dev Upgradeable version of the {DataServicePausable} contract. * @dev This contract inherits from {DataService} which needs to be initialized, please see * {DataService} for detailed instructions. * @custom:security-contact Please email security+contracts@thegraph.com if you find any diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index 0bb600a01..a6af01533 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -12,8 +12,9 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.s /** * @title Rescuable contract - * @dev Allows a contract to have a function to rescue tokens sent by mistake. - * The contract must implement the external rescueTokens function or similar, + * @author Edge & Node + * @notice Allows a contract to have a function to rescue tokens sent by mistake. + * @dev The contract must implement the external rescueTokens function or similar, * that calls this contract's _rescueTokens. * @dev Note that this extension does not provide an external function to set * rescuers. This should be implemented in the derived contract. @@ -63,7 +64,7 @@ abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { } /** - * @dev Allows rescuing tokens sent to this contract + * @notice Allows rescuing tokens sent to this contract * @param _to Destination address to send the tokens * @param _token Address of the token being rescued * @param _tokens Amount of tokens to pull diff --git a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol index 06612913d..42f4a7de9 100644 --- a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol +++ b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol @@ -1,10 +1,14 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities + import { IHorizonStaking } from "@graphprotocol/interfaces/contracts/horizon/IHorizonStaking.sol"; /** * @title ProvisionTracker library + * @author Edge & Node * @notice A library to facilitate tracking of "used tokens" on Graph Horizon provisions. This can be used to * ensure data services have enough economic security (provisioned stake) to back the payments they collect for * their services. diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index db5a9e8f5..9d0db415b 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -1,6 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events +// solhint-disable gas-strict-inequalities + import { IHorizonStaking } from "@graphprotocol/interfaces/contracts/horizon/IHorizonStaking.sol"; import { UintRange } from "../../libraries/UintRange.sol"; @@ -12,6 +16,7 @@ import { ProvisionManagerV1Storage } from "./ProvisionManagerStorage.sol"; /** * @title ProvisionManager contract + * @author Edge & Node * @notice A helper contract that implements several provision management functions. * @dev Provides utilities to verify provision parameters are within an acceptable range. Each * parameter has an overridable setter and getter for the validity range, and a checker that reverts diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol index 5931c66e5..d2d3495ba 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol @@ -3,6 +3,8 @@ pragma solidity 0.8.27; /** * @title Storage layout for the {ProvisionManager} helper contract. + * @author Edge & Node + * @notice Storage layout for the ProvisionManager helper contract * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/horizon/contracts/libraries/Denominations.sol b/packages/horizon/contracts/libraries/Denominations.sol index 46cff3516..abd0ac9a6 100644 --- a/packages/horizon/contracts/libraries/Denominations.sol +++ b/packages/horizon/contracts/libraries/Denominations.sol @@ -3,7 +3,8 @@ pragma solidity 0.8.27; /** * @title Denominations library - * @dev Provides a list of ground denominations for those tokens that cannot be represented by an ERC20. + * @author Edge & Node + * @notice Provides a list of ground denominations for those tokens that cannot be represented by an ERC20 * For now, the only needed is the native token that could be ETH, MATIC, or other depending on the layer being operated. * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. diff --git a/packages/horizon/contracts/libraries/LibFixedMath.sol b/packages/horizon/contracts/libraries/LibFixedMath.sol index 704617b40..2468721b2 100644 --- a/packages/horizon/contracts/libraries/LibFixedMath.sol +++ b/packages/horizon/contracts/libraries/LibFixedMath.sol @@ -20,8 +20,12 @@ pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable function-max-lines, gas-strict-inequalities + /** * @title LibFixedMath + * @author Edge & Node * @notice This library provides fixed-point arithmetic operations. * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. @@ -36,12 +40,20 @@ library LibFixedMath { // -63.875 int256 private constant EXP_MIN_VAL = -int256(0x0000000000000000000000000000001ff0000000000000000000000000000000); - /// @dev Get one as a fixed-point number. + /** + * @notice Get one as a fixed-point number + * @return f The fixed-point representation of one + */ function one() internal pure returns (int256 f) { f = FIXED_1; } - /// @dev Returns the addition of two fixed point numbers, reverting on overflow. + /** + * @notice Returns the subtraction of two fixed point numbers, reverting on overflow + * @param a The first fixed point number + * @param b The second fixed point number to subtract + * @return c The result of a - b + */ function sub(int256 a, int256 b) internal pure returns (int256 c) { if (b == MIN_FIXED_VAL) { revert("out-of-bounds"); @@ -49,19 +61,34 @@ library LibFixedMath { c = _add(a, -b); } - /// @dev Returns the multiplication of two fixed point numbers, reverting on overflow. + /** + * @notice Returns the multiplication of two fixed point numbers, reverting on overflow + * @param a The first fixed point number + * @param b The second fixed point number + * @return c The result of a * b + */ function mul(int256 a, int256 b) internal pure returns (int256 c) { c = _mul(a, b) / FIXED_1; } - /// @dev Performs (a * n) / d, without scaling for precision. + /** + * @notice Performs (a * n) / d, without scaling for precision + * @param a The first fixed point number + * @param n The numerator + * @param d The denominator + * @return c The result of (a * n) / d + */ function mulDiv(int256 a, int256 n, int256 d) internal pure returns (int256 c) { c = _div(_mul(a, n), d); } - /// @dev Returns the unsigned integer result of multiplying a fixed-point - /// number with an integer, reverting if the multiplication overflows. - /// Negative results are clamped to zero. + /** + * @notice Returns the unsigned integer result of multiplying a fixed-point number with an integer + * @dev Negative results are clamped to zero. Reverts if the multiplication overflows. + * @param f Fixed-point number + * @param u Unsigned integer + * @return Unsigned integer result, clamped to zero if negative + */ function uintMul(int256 f, uint256 u) internal pure returns (uint256) { if (int256(u) < int256(0)) { revert("out-of-bounds"); @@ -73,17 +100,30 @@ library LibFixedMath { return uint256(uint256(c) >> 127); } - /// @dev Convert signed `n` / `d` to a fixed-point number. + /** + * @notice Convert signed `n` / `d` to a fixed-point number + * @param n Numerator + * @param d Denominator + * @return f Fixed-point representation of n/d + */ function toFixed(int256 n, int256 d) internal pure returns (int256 f) { f = _div(_mul(n, FIXED_1), d); } - /// @dev Convert a fixed-point number to an integer. + /** + * @notice Convert a fixed-point number to an integer + * @param f Fixed-point number + * @return n Integer representation + */ function toInteger(int256 f) internal pure returns (int256 n) { return f / FIXED_1; } - /// @dev Compute the natural exponent for a fixed-point number EXP_MIN_VAL <= `x` <= 1 + /** + * @notice Compute the natural exponent for a fixed-point number EXP_MIN_VAL <= `x` <= 1 + * @param x Fixed-point number to compute exponent for + * @return r The natural exponent of x + */ function exp(int256 x) internal pure returns (int256 r) { if (x < EXP_MIN_VAL) { // Saturate to zero below EXP_MIN_VAL. @@ -205,7 +245,12 @@ library LibFixedMath { } } - /// @dev Returns the multiplication two numbers, reverting on overflow. + /** + * @notice Returns the multiplication of two numbers, reverting on overflow + * @param a First number + * @param b Second number + * @return c The result of a * b + */ function _mul(int256 a, int256 b) private pure returns (int256 c) { if (a == 0 || b == 0) { return 0; @@ -218,7 +263,12 @@ library LibFixedMath { } } - /// @dev Returns the division of two numbers, reverting on division by zero. + /** + * @notice Returns the division of two numbers, reverting on division by zero + * @param a Dividend + * @param b Divisor + * @return c The result of a / b + */ function _div(int256 a, int256 b) private pure returns (int256 c) { if (b == 0) { revert("overflow"); @@ -231,7 +281,12 @@ library LibFixedMath { } } - /// @dev Adds two numbers, reverting on overflow. + /** + * @notice Adds two numbers, reverting on overflow + * @param a First number + * @param b Second number + * @return c The result of a + b + */ function _add(int256 a, int256 b) private pure returns (int256 c) { unchecked { c = a + b; diff --git a/packages/horizon/contracts/libraries/LinkedList.sol b/packages/horizon/contracts/libraries/LinkedList.sol index 9d3305329..083b1f436 100644 --- a/packages/horizon/contracts/libraries/LinkedList.sol +++ b/packages/horizon/contracts/libraries/LinkedList.sol @@ -2,10 +2,14 @@ pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-increment-by-one, gas-strict-inequalities + import { ILinkedList } from "@graphprotocol/interfaces/contracts/horizon/internal/ILinkedList.sol"; /** * @title LinkedList library + * @author Edge & Node * @notice A library to manage singly linked lists. * * The library makes no assumptions about the contents of the items, the only diff --git a/packages/horizon/contracts/libraries/MathUtils.sol b/packages/horizon/contracts/libraries/MathUtils.sol index fc81e9608..6c0a09a1a 100644 --- a/packages/horizon/contracts/libraries/MathUtils.sol +++ b/packages/horizon/contracts/libraries/MathUtils.sol @@ -1,23 +1,29 @@ // SPDX-License-Identifier: GPL-2.0-or-later +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities + pragma solidity 0.8.27; /** * @title MathUtils Library + * @author Edge & Node * @notice A collection of functions to perform math operations * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ library MathUtils { /** - * @dev Calculates the weighted average of two values pondering each of these - * values based on configured weights. The contribution of each value N is + * @notice Calculates the weighted average of two values pondering each of these + * values based on configured weights + * @dev The contribution of each value N is * weightN/(weightA + weightB). The calculation rounds up to ensure the result * is always equal or 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 + * @return The weighted average result */ function weightedAverageRoundingUp( uint256 valueA, @@ -29,7 +35,7 @@ library MathUtils { } /** - * @dev Returns the minimum of two numbers. + * @notice Returns the minimum of two numbers * @param x The first number * @param y The second number * @return The minimum of the two numbers @@ -39,7 +45,7 @@ library MathUtils { } /** - * @dev Returns the difference between two numbers or zero if negative. + * @notice Returns the difference between two numbers or zero if negative * @param x The first number * @param y The second number * @return The difference between the two numbers or zero if negative diff --git a/packages/horizon/contracts/libraries/PPMMath.sol b/packages/horizon/contracts/libraries/PPMMath.sol index a7966c91d..998a912e8 100644 --- a/packages/horizon/contracts/libraries/PPMMath.sol +++ b/packages/horizon/contracts/libraries/PPMMath.sol @@ -1,8 +1,12 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities + /** * @title PPMMath library + * @author Edge & Node * @notice A library for handling calculations with parts per million (PPM) amounts. * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. diff --git a/packages/horizon/contracts/libraries/UintRange.sol b/packages/horizon/contracts/libraries/UintRange.sol index 69d3f5d8a..7c9bdfdd8 100644 --- a/packages/horizon/contracts/libraries/UintRange.sol +++ b/packages/horizon/contracts/libraries/UintRange.sol @@ -1,8 +1,12 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities + /** * @title UintRange library + * @author Edge & Node * @notice A library for handling range checks on uint256 values. * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. diff --git a/packages/horizon/contracts/mocks/ControllerMock.sol b/packages/horizon/contracts/mocks/ControllerMock.sol index 638387f0c..415e48c5e 100644 --- a/packages/horizon/contracts/mocks/ControllerMock.sol +++ b/packages/horizon/contracts/mocks/ControllerMock.sol @@ -7,22 +7,30 @@ import { IManaged } from "@graphprotocol/interfaces/contracts/contracts/governan /** * @title Graph Controller contract (mock) + * @author Edge & Node + * @notice Mock implementation of the Graph Controller contract for testing * @dev Controller is a registry of contracts for convenience. Inspired by Livepeer: * https://github.com/livepeer/protocol/blob/streamflow/contracts/Controller.sol */ contract ControllerMock is IController { /// @dev Track contract ids to contract proxy address mapping(bytes32 contractName => address contractAddress) private _registry; + + /// @notice Address of the governor address public governor; bool internal _paused; bool internal _partialPaused; address internal _pauseGuardian; - /// Emitted when the proxy address for a protocol contract has been set - event SetContractProxy(bytes32 indexed id, address contractAddress); + /** + * @notice Emitted when the proxy address for a protocol contract has been set + * @param id The contract identifier + * @param contractAddress The new contract address + */ + event SetContractProxy(bytes32 indexed id, address indexed contractAddress); /** - * Constructor for the Controller mock + * @notice Constructor for the Controller mock * @param governor_ Address of the governor */ constructor(address governor_) { diff --git a/packages/horizon/contracts/mocks/CurationMock.sol b/packages/horizon/contracts/mocks/CurationMock.sol index ea3df0587..9de0fea16 100644 --- a/packages/horizon/contracts/mocks/CurationMock.sol +++ b/packages/horizon/contracts/mocks/CurationMock.sol @@ -2,17 +2,38 @@ pragma solidity 0.8.27; +/** + * @title CurationMock + * @author Edge & Node + * @notice Mock implementation of curation functionality for testing + */ contract CurationMock { + /// @notice Mapping of subgraph deployment ID to curation tokens mapping(bytes32 subgraphDeploymentID => uint256 tokens) public curation; + /** + * @notice Signal curation tokens for a subgraph deployment + * @param subgraphDeploymentID The subgraph deployment ID + * @param tokens The amount of tokens to signal + */ function signal(bytes32 subgraphDeploymentID, uint256 tokens) public { curation[subgraphDeploymentID] += tokens; } + /** + * @notice Check if a subgraph deployment is curated + * @param subgraphDeploymentID The subgraph deployment ID + * @return True if the subgraph deployment has curation tokens + */ function isCurated(bytes32 subgraphDeploymentID) public view returns (bool) { return curation[subgraphDeploymentID] != 0; } + /** + * @notice Collect curation tokens for a subgraph deployment + * @param subgraphDeploymentID The subgraph deployment ID + * @param tokens The amount of tokens to collect + */ function collect(bytes32 subgraphDeploymentID, uint256 tokens) external { curation[subgraphDeploymentID] += tokens; } diff --git a/packages/horizon/contracts/mocks/Dummy.sol b/packages/horizon/contracts/mocks/Dummy.sol index e6a575d0f..72b4e1a67 100644 --- a/packages/horizon/contracts/mocks/Dummy.sol +++ b/packages/horizon/contracts/mocks/Dummy.sol @@ -2,4 +2,9 @@ pragma solidity 0.8.27; +/** + * @title Dummy + * @author Edge & Node + * @notice Empty dummy contract for testing purposes + */ contract Dummy {} diff --git a/packages/horizon/contracts/mocks/EpochManagerMock.sol b/packages/horizon/contracts/mocks/EpochManagerMock.sol index 4c00fb29c..4030dc19c 100644 --- a/packages/horizon/contracts/mocks/EpochManagerMock.sol +++ b/packages/horizon/contracts/mocks/EpochManagerMock.sol @@ -4,16 +4,29 @@ pragma solidity 0.8.27; import { IEpochManager } from "@graphprotocol/interfaces/contracts/contracts/epochs/IEpochManager.sol"; +/** + * @title EpochManagerMock + * @author Edge & Node + * @notice Mock implementation of the EpochManager for testing + */ contract EpochManagerMock is IEpochManager { // -- Variables -- + /// @notice Length of an epoch in blocks uint256 public epochLength; + /// @notice Last epoch that was run uint256 public lastRunEpoch; + /// @notice Last epoch when the length was updated uint256 public lastLengthUpdateEpoch; + /// @notice Block number when the length was last updated uint256 public lastLengthUpdateBlock; // -- Configuration -- + /** + * @notice Set the epoch length + * @param epochLength_ New epoch length in blocks + */ function setEpochLength(uint256 epochLength_) public { lastLengthUpdateEpoch = 1; lastLengthUpdateBlock = blockNum(); @@ -22,41 +35,78 @@ contract EpochManagerMock is IEpochManager { // -- Epochs + /** + * @notice Run the current epoch + */ function runEpoch() public { lastRunEpoch = currentEpoch(); } // -- Getters -- + /** + * @notice Check if the current epoch has been run + * @return True if the current epoch has been run + */ function isCurrentEpochRun() public view returns (bool) { return lastRunEpoch == currentEpoch(); } + /** + * @notice Get the current block number + * @return The current block number + */ function blockNum() public view returns (uint256) { return block.number; } + /** + * @notice Get the hash of a specific block + * @param block_ Block number to get hash for + * @return The block hash + */ function blockHash(uint256 block_) public view returns (bytes32) { return blockhash(block_); } + /** + * @notice Get the current epoch number + * @return The current epoch number + */ function currentEpoch() public view returns (uint256) { return lastLengthUpdateEpoch + epochsSinceUpdate(); } + /** + * @notice Get the block number when the current epoch started + * @return The block number when the current epoch started + */ function currentEpochBlock() public view returns (uint256) { return lastLengthUpdateBlock + (epochsSinceUpdate() * epochLength); } + /** + * @notice Get the number of blocks since the current epoch started + * @return The number of blocks since the current epoch started + */ function currentEpochBlockSinceStart() public view returns (uint256) { return blockNum() - currentEpochBlock(); } + /** + * @notice Get the number of epochs since a given epoch + * @param epoch_ The epoch to compare against + * @return The number of epochs since the given epoch + */ function epochsSince(uint256 epoch_) public view returns (uint256) { uint256 epoch = currentEpoch(); return epoch_ < epoch ? (epoch - epoch_) : 0; } + /** + * @notice Get the number of epochs since the last length update + * @return The number of epochs since the last length update + */ function epochsSinceUpdate() public view returns (uint256) { return (blockNum() - lastLengthUpdateBlock) / epochLength; } diff --git a/packages/horizon/contracts/mocks/MockGRTToken.sol b/packages/horizon/contracts/mocks/MockGRTToken.sol index 235999ae5..3186aeb1c 100644 --- a/packages/horizon/contracts/mocks/MockGRTToken.sol +++ b/packages/horizon/contracts/mocks/MockGRTToken.sol @@ -2,29 +2,67 @@ pragma solidity 0.8.27; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; +/** + * @title MockGRTToken + * @author Edge & Node + * @notice Mock implementation of the Graph Token for testing + */ contract MockGRTToken is ERC20, IGraphToken { + /** + * @notice Constructor for the MockGRTToken + */ constructor() ERC20("Graph Token", "GRT") {} + /** + * @notice Burn tokens from the caller's account + * @param tokens Amount of tokens to burn + */ function burn(uint256 tokens) external { _burn(msg.sender, tokens); } + /** + * @notice Burn tokens from a specific account + * @param from Account to burn tokens from + * @param tokens Amount of tokens to burn + */ function burnFrom(address from, uint256 tokens) external { _burn(from, tokens); } // -- Mint Admin -- + /** + * @notice Add a minter (mock implementation - does nothing) + * @param account Account to add as minter + */ function addMinter(address account) external {} + /** + * @notice Remove a minter (mock implementation - does nothing) + * @param account Account to remove as minter + */ function removeMinter(address account) external {} + /** + * @notice Renounce minter role (mock implementation - does nothing) + */ function renounceMinter() external {} // -- Permit -- + /** + * @notice Permit function for gasless approvals (mock implementation - does nothing) + * @param owner Token owner + * @param spender Spender address + * @param value Amount to approve + * @param deadline Deadline for the permit + * @param v Recovery byte of the signature + * @param r First 32 bytes of the signature + * @param s Second 32 bytes of the signature + */ function permit( address owner, address spender, @@ -37,12 +75,34 @@ contract MockGRTToken is ERC20, IGraphToken { // -- Allowance -- + /** + * @notice Increase allowance (mock implementation - does nothing) + * @param spender Spender address + * @param addedValue Amount to add to allowance + * @return Always returns false in mock + */ function increaseAllowance(address spender, uint256 addedValue) external returns (bool) {} + /** + * @notice Decrease allowance (mock implementation - does nothing) + * @param spender Spender address + * @param subtractedValue Amount to subtract from allowance + * @return Always returns false in mock + */ function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool) {} + /** + * @notice Check if an account is a minter (mock implementation - always returns false) + * @param account Account to check + * @return Always returns false in mock + */ function isMinter(address account) external view returns (bool) {} + /** + * @notice Mint tokens to an account + * @param to Account to mint tokens to + * @param tokens Amount of tokens to mint + */ function mint(address to, uint256 tokens) public { _mint(to, tokens); } diff --git a/packages/horizon/contracts/mocks/RewardsManagerMock.sol b/packages/horizon/contracts/mocks/RewardsManagerMock.sol index 300e7efe2..2883f0175 100644 --- a/packages/horizon/contracts/mocks/RewardsManagerMock.sol +++ b/packages/horizon/contracts/mocks/RewardsManagerMock.sol @@ -4,23 +4,57 @@ pragma solidity 0.8.27; import { MockGRTToken } from "./MockGRTToken.sol"; +/** + * @title RewardsManagerMock + * @author Edge & Node + * @notice Mock implementation of the RewardsManager for testing + */ contract RewardsManagerMock { // -- Variables -- + /// @notice The mock GRT token contract MockGRTToken public token; uint256 private _rewards; // -- Constructor -- + /** + * @notice Constructor for the RewardsManager mock + * @param token_ The mock GRT token contract + * @param rewards The amount of rewards to distribute + */ constructor(MockGRTToken token_, uint256 rewards) { token = token_; _rewards = rewards; } - function takeRewards(address) external returns (uint256) { + /** + * @notice Take rewards for an allocation + * @param allocationID The allocation ID (unused in this mock) + * @return The amount of rewards taken + */ + function takeRewards(address allocationID) external returns (uint256) { + allocationID; // silence unused variable warning token.mint(msg.sender, _rewards); return _rewards; } - function onSubgraphAllocationUpdate(bytes32) public returns (uint256) {} - function onSubgraphSignalUpdate(bytes32 subgraphDeploymentID) external returns (uint256) {} + /** + * @notice Handle subgraph allocation update (mock implementation) + * @param subgraphDeploymentID The subgraph deployment ID (unused in this mock) + * @return Always returns 0 in mock + */ + function onSubgraphAllocationUpdate(bytes32 subgraphDeploymentID) public pure returns (uint256) { + subgraphDeploymentID; // silence unused variable warning + return 0; + } + + /** + * @notice Handle subgraph signal update (mock implementation) + * @param subgraphDeploymentID The subgraph deployment ID (unused in this mock) + * @return Always returns 0 in mock + */ + function onSubgraphSignalUpdate(bytes32 subgraphDeploymentID) external pure returns (uint256) { + subgraphDeploymentID; // silence unused variable warning + return 0; + } } diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index e82758b0e..144a2daa1 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -1,7 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable function-max-lines + +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { IGraphPayments } from "@graphprotocol/interfaces/contracts/horizon/IGraphPayments.sol"; import { IHorizonStakingTypes } from "@graphprotocol/interfaces/contracts/horizon/internal/IHorizonStakingTypes.sol"; @@ -14,6 +17,7 @@ import { GraphDirectory } from "../utilities/GraphDirectory.sol"; /** * @title GraphPayments contract + * @author Edge & Node * @notice This contract is part of the Graph Horizon payments protocol. It's designed * to pull funds (GRT) from the {PaymentsEscrow} and distribute them according to a * set of pre established rules. diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index bcced0412..50a5386c9 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -1,7 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities + +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { IGraphPayments } from "@graphprotocol/interfaces/contracts/horizon/IGraphPayments.sol"; import { IPaymentsEscrow } from "@graphprotocol/interfaces/contracts/horizon/IPaymentsEscrow.sol"; @@ -13,6 +16,7 @@ import { GraphDirectory } from "../utilities/GraphDirectory.sol"; /** * @title PaymentsEscrow contract + * @author Edge & Node * @dev Implements the {IPaymentsEscrow} interface * @notice This contract is part of the Graph Horizon payments protocol. It holds the funds (GRT) * for payments made through the payments protocol for services provided diff --git a/packages/horizon/contracts/payments/collectors/GraphTallyCollector.sol b/packages/horizon/contracts/payments/collectors/GraphTallyCollector.sol index 0ede499e0..eb33d931c 100644 --- a/packages/horizon/contracts/payments/collectors/GraphTallyCollector.sol +++ b/packages/horizon/contracts/payments/collectors/GraphTallyCollector.sol @@ -1,6 +1,11 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-small-strings +// solhint-disable gas-strict-inequalities +// solhint-disable function-max-lines + import { IGraphPayments } from "@graphprotocol/interfaces/contracts/horizon/IGraphPayments.sol"; import { IGraphTallyCollector } from "@graphprotocol/interfaces/contracts/horizon/IGraphTallyCollector.sol"; import { IPaymentsCollector } from "@graphprotocol/interfaces/contracts/horizon/IPaymentsCollector.sol"; @@ -14,6 +19,7 @@ import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; /** * @title GraphTallyCollector contract + * @author Edge & Node * @dev Implements the {IGraphTallyCollector}, {IPaymentCollector} and {IAuthorizable} interfaces. * @notice A payments collector contract that can be used to collect payments using a GraphTally RAV (Receipt Aggregate Voucher). * @dev Note that the contract expects the RAV aggregate value to be monotonically increasing, each successive RAV for the same @@ -185,9 +191,9 @@ contract GraphTallyCollector is EIP712, GraphDirectory, Authorizable, IGraphTall } /** - * @dev Recovers the signer address of a signed ReceiptAggregateVoucher (RAV). - * @param _signedRAV The SignedRAV containing the RAV and its signature. - * @return The address of the signer. + * @notice Recovers the signer address of a signed ReceiptAggregateVoucher (RAV) + * @param _signedRAV The SignedRAV containing the RAV and its signature + * @return The address of the signer */ function _recoverRAVSigner(SignedRAV memory _signedRAV) private view returns (address) { bytes32 messageHash = _encodeRAV(_signedRAV.rav); @@ -195,9 +201,9 @@ contract GraphTallyCollector is EIP712, GraphDirectory, Authorizable, IGraphTall } /** - * @dev Computes the hash of a ReceiptAggregateVoucher (RAV). - * @param _rav The RAV for which to compute the hash. - * @return The hash of the RAV. + * @notice Computes the hash of a ReceiptAggregateVoucher (RAV) + * @param _rav The RAV for which to compute the hash + * @return The hash of the RAV */ function _encodeRAV(ReceiptAggregateVoucher memory _rav) private view returns (bytes32) { return diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index ff675fdd6..73f48c354 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -1,8 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities +// solhint-disable gas-increment-by-one +// solhint-disable function-max-lines + pragma solidity 0.8.27; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStakingMain } from "@graphprotocol/interfaces/contracts/horizon/internal/IHorizonStakingMain.sol"; import { IHorizonStakingExtension } from "@graphprotocol/interfaces/contracts/horizon/internal/IHorizonStakingExtension.sol"; import { IGraphPayments } from "@graphprotocol/interfaces/contracts/horizon/IGraphPayments.sol"; @@ -17,6 +22,7 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; /** * @title HorizonStaking contract + * @author Edge & Node * @notice The {HorizonStaking} contract allows service providers to stake and provision tokens to verifiers to be used * as economic security for a service. It also allows delegators to delegate towards a service provider provision. * @dev Implements the {IHorizonStakingMain} interface. @@ -69,11 +75,10 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } /** - * @dev The staking contract is upgradeable however we still use the constructor to set - * a few immutable variables. - * @param controller The address of the Graph controller contract. - * @param stakingExtensionAddress The address of the staking extension contract. - * @param subgraphDataServiceAddress The address of the subgraph data service. + * @notice The staking contract is upgradeable however we still use the constructor to set a few immutable variables + * @param controller The address of the Graph controller contract + * @param stakingExtensionAddress The address of the staking extension contract + * @param subgraphDataServiceAddress The address of the subgraph data service */ constructor( address controller, @@ -88,8 +93,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @dev This function does not return to its internal call site, it will return directly to the * external caller. */ - // solhint-disable-next-line payable-fallback, no-complex-fallback fallback() external { + // solhint-disable-previous-line payable-fallback, no-complex-fallback address extensionImpl = STAKING_EXTENSION_ADDRESS; // solhint-disable-next-line no-inline-assembly assembly { @@ -681,8 +686,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @dev TRANSITION PERIOD: During the transition period, only the subgraph data service can be used as a verifier. This * prevents an escape hatch for legacy allocation stake. * @param _serviceProvider The service provider address - * @param _verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) * @param _tokens The amount of tokens that will be locked and slashable + * @param _verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) * @param _maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing * @param _thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision */ diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index 2428e1e98..9c52a2171 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -1,5 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities + pragma solidity 0.8.27; import { IHorizonStakingTypes } from "@graphprotocol/interfaces/contracts/horizon/internal/IHorizonStakingTypes.sol"; @@ -17,6 +20,7 @@ import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; /** * @title HorizonStakingBase contract + * @author Edge & Node * @notice This contract is the base staking contract implementing storage getters for both internal * and external use. * @dev Implementation of the {IHorizonStakingBase} interface. @@ -42,10 +46,9 @@ abstract contract HorizonStakingBase is address internal immutable SUBGRAPH_DATA_SERVICE_ADDRESS; /** - * @dev The staking contract is upgradeable however we still use the constructor to set - * a few immutable variables. - * @param controller The address of the Graph controller contract. - * @param subgraphDataServiceAddress The address of the subgraph data service. + * @notice The staking contract is upgradeable however we still use the constructor to set a few immutable variables + * @param controller The address of the Graph controller contract + * @param subgraphDataServiceAddress The address of the subgraph data service */ constructor(address controller, address subgraphDataServiceAddress) Managed(controller) { SUBGRAPH_DATA_SERVICE_ADDRESS = subgraphDataServiceAddress; diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 3480a5c4d..b1adcde0d 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -2,8 +2,11 @@ pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable function-max-lines, gas-strict-inequalities + import { ICuration } from "@graphprotocol/interfaces/contracts/contracts/curation/ICuration.sol"; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStakingExtension } from "@graphprotocol/interfaces/contracts/horizon/internal/IHorizonStakingExtension.sol"; import { IRewardsIssuer } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsIssuer.sol"; @@ -16,6 +19,7 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; /** * @title Horizon Staking extension contract + * @author Edge & Node * @notice The {HorizonStakingExtension} contract implements the legacy functionality required to support the transition * to the Horizon Staking contract. It allows indexers to close allocations and collect pending query fees, but it * does not allow for the creation of new allocations. This should allow indexers to migrate to a subgraph data service @@ -39,10 +43,9 @@ contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension } /** - * @dev The staking contract is upgradeable however we still use the constructor to set - * a few immutable variables. - * @param controller The address of the Graph controller contract. - * @param subgraphDataServiceAddress The address of the subgraph data service. + * @notice The staking contract is upgradeable however we still use the constructor to set a few immutable variables + * @param controller The address of the Graph controller contract + * @param subgraphDataServiceAddress The address of the subgraph data service */ constructor( address controller, @@ -265,7 +268,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension } /** - * @dev Collect tax to burn for an amount of tokens. + * @notice Collect tax to burn for an amount of tokens * @param _tokens Total tokens received used to calculate the amount of tax to collect * @param _percentage Percentage of tokens to burn as tax * @return Amount of tax charged @@ -277,7 +280,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension } /** - * @dev Triggers an update of rewards due to a change in allocations. + * @notice Triggers an update of rewards due to a change in allocations * @param _subgraphDeploymentID Subgraph deployment updated */ function _updateRewards(bytes32 _subgraphDeploymentID) private { @@ -285,7 +288,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension } /** - * @dev Assign rewards for the closed allocation to indexer and delegators. + * @notice Assign rewards for the closed allocation to indexer and delegators * @param _allocationID Allocation * @param _indexer Address of the indexer that did the allocation */ @@ -307,7 +310,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension } /** - * @dev Send rewards to the appropriate destination. + * @notice Send rewards to the appropriate destination * @param _tokens Number of rewards tokens * @param _beneficiary Address of the beneficiary of rewards * @param _restake Whether to restake or not @@ -326,7 +329,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension } /** - * @dev Close an allocation and free the staked tokens. + * @notice Close an allocation and free the staked tokens * @param _allocationID The allocation identifier * @param _poi Proof of indexing submitted for the allocated period */ @@ -390,8 +393,8 @@ contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension } /** - * @dev Collect the delegation rewards for query fees. - * This function will assign the collected fees to the delegation pool. + * @notice Collect the delegation rewards for query fees + * @dev This function will assign the collected fees to the delegation pool * @param _indexer Indexer to which the tokens to distribute are related * @param _tokens Total tokens received used to calculate the amount of fees to collect * @return Amount of delegation rewards @@ -408,8 +411,8 @@ contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension } /** - * @dev Collect the delegation rewards for indexing. - * This function will assign the collected fees to the delegation pool. + * @notice Collect the delegation rewards for indexing + * @dev This function will assign the collected fees to the delegation pool * @param _indexer Indexer to which the tokens to distribute are related * @param _tokens Total tokens received used to calculate the amount of fees to collect * @return Amount of delegation rewards @@ -426,8 +429,8 @@ contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension } /** - * @dev Collect the curation fees for a subgraph deployment from an amount of tokens. - * This function transfer curation fees to the Curation contract by calling Curation.collect + * @notice Collect the curation fees for a subgraph deployment from an amount of tokens + * @dev This function transfer curation fees to the Curation contract by calling Curation.collect * @param _subgraphDeploymentID Subgraph deployment to which the curation fees are related * @param _tokens Total tokens received used to calculate the amount of fees to collect * @param _curationCut Percentage of tokens to collect as fees @@ -461,7 +464,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension } /** - * @dev Return the current state of an allocation + * @notice Return the current state of an allocation * @param _allocationID Allocation identifier * @return AllocationState enum with the state of the allocation */ diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index 19dc65f11..5f63af9df 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -11,7 +11,8 @@ import { ILinkedList } from "@graphprotocol/interfaces/contracts/horizon/interna /** * @title HorizonStakingV1Storage - * @notice This contract holds all the storage variables for the Staking contract. + * @author Edge & Node + * @notice This contract holds all the storage variables for the Staking contract * @dev Deprecated variables are kept to support the transition to Horizon Staking. * They can eventually be collapsed into a single storage slot. * @custom:security-contact Please email security+contracts@thegraph.com if you find any diff --git a/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol b/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol index b137079b3..974e7197b 100644 --- a/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol +++ b/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol @@ -6,6 +6,7 @@ import { LibFixedMath } from "../../libraries/LibFixedMath.sol"; /** * @title ExponentialRebates library + * @author Edge & Node * @notice A library to compute query fee rebates using an exponential formula * @dev This is only used for backwards compatibility in HorizonStaking, and should * be removed after the transition period. @@ -16,21 +17,22 @@ library ExponentialRebates { /// @dev Maximum value of the exponent for which to compute the exponential before clamping to zero. uint32 private constant MAX_EXPONENT = 15; - /// @dev The exponential formula used to compute fee-based rewards for - /// staking pools in a given epoch. This function does not perform - /// bounds checking on the inputs, but the following conditions - /// need to be true: - /// 0 <= alphaNumerator / alphaDenominator <= 1 - /// 0 < lambdaNumerator / lambdaDenominator - /// The exponential rebates function has the form: - /// `(1 - alpha * exp ^ (-lambda * stake / fees)) * fees` - /// @param fees Fees generated by indexer in the staking pool. - /// @param stake Stake attributed to the indexer in the staking pool. - /// @param alphaNumerator Numerator of `alpha` in the rebates function. - /// @param alphaDenominator Denominator of `alpha` in the rebates function. - /// @param lambdaNumerator Numerator of `lambda` in the rebates function. - /// @param lambdaDenominator Denominator of `lambda` in the rebates function. - /// @return rewards Rewards owed to the staking pool. + /** + * @notice The exponential formula used to compute fee-based rewards for staking pools in a given epoch + * @dev This function does not perform bounds checking on the inputs, but the following conditions + * need to be true: + * 0 <= alphaNumerator / alphaDenominator <= 1 + * 0 < lambdaNumerator / lambdaDenominator + * The exponential rebates function has the form: + * `(1 - alpha * exp ^ (-lambda * stake / fees)) * fees` + * @param fees Fees generated by indexer in the staking pool + * @param stake Stake attributed to the indexer in the staking pool + * @param alphaNumerator Numerator of `alpha` in the rebates function + * @param alphaDenominator Denominator of `alpha` in the rebates function + * @param lambdaNumerator Numerator of `lambda` in the rebates function + * @param lambdaDenominator Denominator of `lambda` in the rebates function + * @return rewards Rewards owed to the staking pool + */ function exponentialRebates( uint256 fees, uint256 stake, diff --git a/packages/horizon/contracts/staking/utilities/Managed.sol b/packages/horizon/contracts/staking/utilities/Managed.sol index b2e36056f..88d2fb7c1 100644 --- a/packages/horizon/contracts/staking/utilities/Managed.sol +++ b/packages/horizon/contracts/staking/utilities/Managed.sol @@ -8,8 +8,9 @@ import { GraphDirectory } from "../../utilities/GraphDirectory.sol"; /** * @title Graph Managed contract - * @dev The Managed contract provides an interface to interact with the Controller. - * For Graph Horizon this contract is mostly a shell that uses {GraphDirectory}, however since the {HorizonStaking} + * @author Edge & Node + * @notice The Managed contract provides an interface to interact with the Controller + * @dev For Graph Horizon this contract is mostly a shell that uses {GraphDirectory}, however since the {HorizonStaking} * contract uses it we need to preserve the storage layout. * Inspired by Livepeer: https://github.com/livepeer/protocol/blob/streamflow/contracts/Controller.sol * @custom:security-contact Please email security+contracts@thegraph.com if you find any @@ -59,8 +60,8 @@ abstract contract Managed is GraphDirectory { } /** - * @dev Initialize the contract - * @param controller_ The address of the Graph controller contract. + * @notice Initialize the contract + * @param controller_ The address of the Graph controller contract */ constructor(address controller_) GraphDirectory(controller_) {} } diff --git a/packages/horizon/contracts/utilities/Authorizable.sol b/packages/horizon/contracts/utilities/Authorizable.sol index 3c77e951e..6af2e677f 100644 --- a/packages/horizon/contracts/utilities/Authorizable.sol +++ b/packages/horizon/contracts/utilities/Authorizable.sol @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities + import { IAuthorizable } from "@graphprotocol/interfaces/contracts/horizon/IAuthorizable.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; @@ -8,6 +11,7 @@ import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/Mes /** * @title Authorizable contract + * @author Edge & Node * @dev Implements the {IAuthorizable} interface. * @notice A mechanism to authorize signers to sign messages on behalf of an authorizer. * Signers cannot be reused for different authorizers. diff --git a/packages/horizon/contracts/utilities/GraphDirectory.sol b/packages/horizon/contracts/utilities/GraphDirectory.sol index 469410c8b..6e657c6d7 100644 --- a/packages/horizon/contracts/utilities/GraphDirectory.sol +++ b/packages/horizon/contracts/utilities/GraphDirectory.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.27; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStaking } from "@graphprotocol/interfaces/contracts/horizon/IHorizonStaking.sol"; import { IGraphPayments } from "@graphprotocol/interfaces/contracts/horizon/IGraphPayments.sol"; import { IPaymentsEscrow } from "@graphprotocol/interfaces/contracts/horizon/IPaymentsEscrow.sol"; @@ -17,6 +17,7 @@ import { ICuration } from "@graphprotocol/interfaces/contracts/contracts/curatio /** * @title GraphDirectory contract + * @author Edge & Node * @notice This contract is meant to be inherited by other contracts that * need to keep track of the addresses in Graph Horizon contracts. * It fetches the addresses from the Controller supplied during construction, diff --git a/packages/horizon/test/unit/utilities/GraphDirectoryImplementation.sol b/packages/horizon/test/unit/utilities/GraphDirectoryImplementation.sol index f62576084..4a88bf0cd 100644 --- a/packages/horizon/test/unit/utilities/GraphDirectoryImplementation.sol +++ b/packages/horizon/test/unit/utilities/GraphDirectoryImplementation.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.27; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStaking } from "@graphprotocol/interfaces/contracts/horizon/IHorizonStaking.sol"; import { IGraphPayments } from "@graphprotocol/interfaces/contracts/horizon/IGraphPayments.sol"; import { IPaymentsEscrow } from "@graphprotocol/interfaces/contracts/horizon/IPaymentsEscrow.sol"; diff --git a/packages/interfaces/README.md b/packages/interfaces/README.md index ff0fe932d..a93f9d544 100644 --- a/packages/interfaces/README.md +++ b/packages/interfaces/README.md @@ -4,7 +4,7 @@ Contract interfaces and types for The Graph protocol. ## Overview -This package contains contract interfaces and types used in dependent packages, which makes building systems that interact with The Graph contracts simpler, as the implementation information is not included. +This package contains contract interfaces and types used in dependent packages. ## Installation @@ -12,6 +12,15 @@ This package contains contract interfaces and types used in dependent packages, pnpm add @graphprotocol/interfaces ``` +## Compiler Version Strategy + +Interface pragma statements use open-ended caret ranges (e.g., `^0.8.22`) rather than exact versions to maximize compatibility with future packages and compiler versions: + +- **Dual-version interfaces** (`^0.7.6 || ^0.8.0` or `^0.7.3 || ^0.8.0`): Maintain compatibility with both Solidity 0.7.x and 0.8.x implementations +- **Modern interfaces** (`^0.8.22`): Allow the use of Solidity 0.8-specific features like custom errors, named mapping parameters, and file-level events + +This approach allows consuming projects to use any compatible compiler version within the specified range. + ## Usage ### Contract interfaces @@ -46,6 +55,16 @@ import { } from '@graphprotocol/interfaces' ``` +#### Available Type Formats + +This package generates TypeScript types in multiple formats to support different environments: + +- **ethers v6** (default): `dist/types/` - Modern ethers.js types (imported from package root) +- **ethers v5**: `dist/types-v5/` - Legacy ethers.js support for projects still using ethers v5 +- **Wagmi**: `dist/wagmi/` - React hooks for the wagmi library + +Import the appropriate version based on your project's dependencies. + ### TypeScript library Additionally, the package exposes a few helper functions to facilitate the creation of fully typed ethers v6 contracts: @@ -57,10 +76,7 @@ Additionally, the package exposes a few helper functions to facilitate the creat | `getAbi` | Gets the ABI for a given contract name. | ```ts -import { - getInterface, - SubgraphService -} from '@graphprotocol/interfaces +import { getInterface, SubgraphService } from '@graphprotocol/interfaces' const subgraphService = new ethers.Contract('0x12...90', getInterface('SubgraphService')) as SubgraphService ``` diff --git a/packages/interfaces/contracts/contracts/arbitrum/IArbToken.sol b/packages/interfaces/contracts/contracts/arbitrum/IArbToken.sol index 35fd7beb3..2a44467cf 100644 --- a/packages/interfaces/contracts/contracts/arbitrum/IArbToken.sol +++ b/packages/interfaces/contracts/contracts/arbitrum/IArbToken.sol @@ -27,20 +27,30 @@ * @title Minimum expected interface for L2 token that interacts with the L2 token bridge (this is the interface necessary * for a custom token that interacts with the bridge, see TestArbCustomToken.sol for an example implementation). */ -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +/** + * @title Arbitrum Token Interface + * @author Edge & Node + * @notice Interface for tokens that can be minted and burned on Arbitrum L2 + */ interface IArbToken { /** * @notice should increase token supply by amount, and should (probably) only be callable by the L1 bridge. + * @param account Account to mint tokens to + * @param amount Amount of tokens to mint */ function bridgeMint(address account, uint256 amount) external; /** * @notice should decrease token supply by amount, and should (probably) only be callable by the L1 bridge. + * @param account Account to burn tokens from + * @param amount Amount of tokens to burn */ function bridgeBurn(address account, uint256 amount) external; /** + * @notice Get the L1 token address * @return address of layer 1 token */ function l1Address() external view returns (address); diff --git a/packages/interfaces/contracts/contracts/arbitrum/IBridge.sol b/packages/interfaces/contracts/contracts/arbitrum/IBridge.sol index 791c2b1a1..7a5b980aa 100644 --- a/packages/interfaces/contracts/contracts/arbitrum/IBridge.sol +++ b/packages/interfaces/contracts/contracts/arbitrum/IBridge.sol @@ -23,9 +23,26 @@ * */ -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events + +/** + * @title Bridge Interface + * @author Edge & Node + * @notice Interface for the Arbitrum Bridge contract + */ interface IBridge { + /** + * @notice Emitted when a message is delivered to the inbox + * @param messageIndex Index of the message + * @param beforeInboxAcc Inbox accumulator before this message + * @param inbox Address of the inbox + * @param kind Type of the message + * @param sender Address that sent the message + * @param messageDataHash Hash of the message data + */ event MessageDelivered( uint256 indexed messageIndex, bytes32 indexed beforeInboxAcc, @@ -35,38 +52,102 @@ interface IBridge { bytes32 messageDataHash ); + /** + * @notice Emitted when a bridge call is triggered + * @param outbox Address of the outbox + * @param destAddr Destination address for the call + * @param amount ETH amount sent with the call + * @param data Calldata for the function call + */ event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data); + /** + * @notice Emitted when an inbox is enabled or disabled + * @param inbox Address of the inbox + * @param enabled Whether the inbox is enabled + */ event InboxToggle(address indexed inbox, bool enabled); + /** + * @notice Emitted when an outbox is enabled or disabled + * @param outbox Address of the outbox + * @param enabled Whether the outbox is enabled + */ event OutboxToggle(address indexed outbox, bool enabled); + /** + * @notice Deliver a message to the inbox + * @param kind Type of the message + * @param sender Address that is sending the message + * @param messageDataHash keccak256 hash of the message data + * @return The message index + */ function deliverMessageToInbox( uint8 kind, address sender, bytes32 messageDataHash ) external payable returns (uint256); + /** + * @notice Execute a call from L2 to L1 + * @param destAddr Contract to call + * @param amount ETH value to send + * @param data Calldata for the function call + * @return success True if the call was successful, false otherwise + * @return returnData Return data from the call + */ function executeCall( address destAddr, uint256 amount, bytes calldata data ) external returns (bool success, bytes memory returnData); - // These are only callable by the admin + /** + * @notice Set the address of an inbox + * @param inbox Address of the inbox + * @param enabled Whether to enable the inbox + */ function setInbox(address inbox, bool enabled) external; + /** + * @notice Set the address of an outbox + * @param inbox Address of the outbox + * @param enabled Whether to enable the outbox + */ function setOutbox(address inbox, bool enabled) external; // View functions + /** + * @notice Get the active outbox address + * @return The active outbox address + */ function activeOutbox() external view returns (address); + /** + * @notice Check if an address is an allowed inbox + * @param inbox Address to check + * @return True if the address is an allowed inbox, false otherwise + */ function allowedInboxes(address inbox) external view returns (bool); + /** + * @notice Check if an address is an allowed outbox + * @param outbox Address to check + * @return True if the address is an allowed outbox, false otherwise + */ function allowedOutboxes(address outbox) external view returns (bool); + /** + * @notice Get the inbox accumulator at a specific index + * @param index Index to query + * @return The inbox accumulator at the given index + */ function inboxAccs(uint256 index) external view returns (bytes32); + /** + * @notice Get the count of messages in the inbox + * @return Number of messages in the inbox + */ function messageCount() external view returns (uint256); } diff --git a/packages/interfaces/contracts/contracts/arbitrum/IInbox.sol b/packages/interfaces/contracts/contracts/arbitrum/IInbox.sol index f216128cf..c8931522b 100644 --- a/packages/interfaces/contracts/contracts/arbitrum/IInbox.sol +++ b/packages/interfaces/contracts/contracts/arbitrum/IInbox.sol @@ -23,14 +23,34 @@ * */ -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; import { IBridge } from "./IBridge.sol"; import { IMessageProvider } from "./IMessageProvider.sol"; +/** + * @title Inbox Interface + * @author Edge & Node + * @notice Interface for the Arbitrum Inbox contract + */ interface IInbox is IMessageProvider { + /** + * @notice Send a message to L2 + * @param messageData Encoded data to send in the message + * @return Message number returned by the inbox + */ function sendL2Message(bytes calldata messageData) external returns (uint256); + /** + * @notice Send an unsigned transaction to L2 + * @param maxGas Maximum gas for the L2 transaction + * @param gasPriceBid Gas price bid for the L2 transaction + * @param nonce Nonce for the transaction + * @param destAddr Destination address on L2 + * @param amount Amount of ETH to send + * @param data Transaction data + * @return Message number returned by the inbox + */ function sendUnsignedTransaction( uint256 maxGas, uint256 gasPriceBid, @@ -40,6 +60,15 @@ interface IInbox is IMessageProvider { bytes calldata data ) external returns (uint256); + /** + * @notice Send a contract transaction to L2 + * @param maxGas Maximum gas for the L2 transaction + * @param gasPriceBid Gas price bid for the L2 transaction + * @param destAddr Destination address on L2 + * @param amount Amount of ETH to send + * @param data Transaction data + * @return Message number returned by the inbox + */ function sendContractTransaction( uint256 maxGas, uint256 gasPriceBid, @@ -48,6 +77,15 @@ interface IInbox is IMessageProvider { bytes calldata data ) external returns (uint256); + /** + * @notice Send an L1-funded unsigned transaction to L2 + * @param maxGas Maximum gas for the L2 transaction + * @param gasPriceBid Gas price bid for the L2 transaction + * @param nonce Nonce for the transaction + * @param destAddr Destination address on L2 + * @param data Transaction data + * @return Message number returned by the inbox + */ function sendL1FundedUnsignedTransaction( uint256 maxGas, uint256 gasPriceBid, @@ -56,6 +94,14 @@ interface IInbox is IMessageProvider { bytes calldata data ) external payable returns (uint256); + /** + * @notice Send an L1-funded contract transaction to L2 + * @param maxGas Maximum gas for the L2 transaction + * @param gasPriceBid Gas price bid for the L2 transaction + * @param destAddr Destination address on L2 + * @param data Transaction data + * @return Message number returned by the inbox + */ function sendL1FundedContractTransaction( uint256 maxGas, uint256 gasPriceBid, @@ -63,6 +109,18 @@ interface IInbox is IMessageProvider { bytes calldata data ) external payable returns (uint256); + /** + * @notice Create a retryable ticket for an L2 transaction + * @param destAddr Destination address on L2 + * @param arbTxCallValue Call value for the L2 transaction + * @param maxSubmissionCost Maximum cost for submitting the ticket + * @param submissionRefundAddress Address to refund submission cost to + * @param valueRefundAddress Address to refund excess value to + * @param maxGas Maximum gas for the L2 transaction + * @param gasPriceBid Gas price bid for the L2 transaction + * @param data Transaction data + * @return Message number returned by the inbox + */ function createRetryableTicket( address destAddr, uint256 arbTxCallValue, @@ -74,15 +132,36 @@ interface IInbox is IMessageProvider { bytes calldata data ) external payable returns (uint256); + /** + * @notice Deposit ETH to L2 + * @param maxSubmissionCost Maximum cost for submitting the deposit + * @return Message number returned by the inbox + */ function depositEth(uint256 maxSubmissionCost) external payable returns (uint256); + /** + * @notice Get the bridge contract + * @return The bridge contract address + */ function bridge() external view returns (IBridge); + /** + * @notice Pause the creation of retryable tickets + */ function pauseCreateRetryables() external; + /** + * @notice Unpause the creation of retryable tickets + */ function unpauseCreateRetryables() external; + /** + * @notice Start rewriting addresses + */ function startRewriteAddress() external; + /** + * @notice Stop rewriting addresses + */ function stopRewriteAddress() external; } diff --git a/packages/interfaces/contracts/contracts/arbitrum/IMessageProvider.sol b/packages/interfaces/contracts/contracts/arbitrum/IMessageProvider.sol index 50b674c70..ca603ac41 100644 --- a/packages/interfaces/contracts/contracts/arbitrum/IMessageProvider.sol +++ b/packages/interfaces/contracts/contracts/arbitrum/IMessageProvider.sol @@ -23,10 +23,24 @@ * */ -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +/** + * @title Message Provider Interface + * @author Edge & Node + * @notice Interface for Arbitrum message providers + */ interface IMessageProvider { + /** + * @notice Emitted when a message is delivered to the inbox + * @param messageNum Message number + * @param data Message data + */ event InboxMessageDelivered(uint256 indexed messageNum, bytes data); + /** + * @notice Emitted when a message is delivered from origin + * @param messageNum Message number + */ event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); } diff --git a/packages/interfaces/contracts/contracts/arbitrum/IOutbox.sol b/packages/interfaces/contracts/contracts/arbitrum/IOutbox.sol index 49617a976..732a99b62 100644 --- a/packages/interfaces/contracts/contracts/arbitrum/IOutbox.sol +++ b/packages/interfaces/contracts/contracts/arbitrum/IOutbox.sol @@ -23,15 +23,38 @@ * */ -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events + +/** + * @title Arbitrum Outbox Interface + * @author Edge & Node + * @notice Interface for the Arbitrum outbox contract + */ interface IOutbox { + /** + * @notice Emitted when an outbox entry is created + * @param batchNum Batch number + * @param outboxEntryIndex Index of the outbox entry + * @param outputRoot Output root hash + * @param numInBatch Number of messages in the batch + */ event OutboxEntryCreated( uint256 indexed batchNum, uint256 outboxEntryIndex, bytes32 outputRoot, uint256 numInBatch ); + + /** + * @notice Emitted when an outbox transaction is executed + * @param destAddr Destination address + * @param l2Sender L2 sender address + * @param outboxEntryIndex Index of the outbox entry + * @param transactionIndex Index of the transaction + */ event OutBoxTransactionExecuted( address indexed destAddr, address indexed l2Sender, @@ -39,19 +62,53 @@ interface IOutbox { uint256 transactionIndex ); + /** + * @notice Get the L2 to L1 sender address + * @return The sender address + */ function l2ToL1Sender() external view returns (address); + /** + * @notice Get the L2 to L1 block number + * @return The block number + */ function l2ToL1Block() external view returns (uint256); + /** + * @notice Get the L2 to L1 Ethereum block number + * @return The Ethereum block number + */ function l2ToL1EthBlock() external view returns (uint256); + /** + * @notice Get the L2 to L1 timestamp + * @return The timestamp + */ function l2ToL1Timestamp() external view returns (uint256); + /** + * @notice Get the L2 to L1 batch number + * @return The batch number + */ function l2ToL1BatchNum() external view returns (uint256); + /** + * @notice Get the L2 to L1 output ID + * @return The output ID + */ function l2ToL1OutputId() external view returns (bytes32); + /** + * @notice Process outgoing messages + * @param sendsData Encoded message data + * @param sendLengths Array of message lengths + */ function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths) external; + /** + * @notice Check if an outbox entry exists + * @param batchNum Batch number to check + * @return True if the entry exists + */ function outboxEntryExists(uint256 batchNum) external view returns (bool); } diff --git a/packages/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol b/packages/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol index 3b12e578e..aa3a018ac 100644 --- a/packages/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol +++ b/packages/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol @@ -23,8 +23,13 @@ * */ -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.3 || ^0.8.0; +/** + * @title Token Gateway Interface + * @author Edge & Node + * @notice Interface for token gateways that handle cross-chain token transfers + */ interface ITokenGateway { /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated // event OutboundTransferInitiated( @@ -46,15 +51,33 @@ interface ITokenGateway { // bytes _data // ); + /** + * @notice Transfer tokens from L1 to L2 or L2 to L1 + * @param token Address of the token being transferred + * @param to Recipient address on the destination chain + * @param amount Amount of tokens to transfer + * @param maxGas Maximum gas for the transaction + * @param gasPriceBid Gas price bid for the transaction + * @param data Additional data for the transfer + * @return Transaction data + */ function outboundTransfer( address token, address to, - uint256 amunt, - uint256 maxas, - uint256 gasPiceBid, + uint256 amount, + uint256 maxGas, + uint256 gasPriceBid, bytes calldata data ) external payable returns (bytes memory); + /** + * @notice Finalize an inbound token transfer + * @param token Address of the token being transferred + * @param from Sender address on the source chain + * @param to Recipient address on the destination chain + * @param amount Amount of tokens being transferred + * @param data Additional data for the transfer + */ function finalizeInboundTransfer( address token, address from, diff --git a/packages/interfaces/contracts/contracts/base/IMulticall.sol b/packages/interfaces/contracts/contracts/base/IMulticall.sol index 10f7fa469..a30be5e7e 100644 --- a/packages/interfaces/contracts/contracts/base/IMulticall.sol +++ b/packages/interfaces/contracts/contracts/base/IMulticall.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; pragma abicoder v2; /** * @title Multicall interface + * @author Edge & Node * @notice Enables calling multiple methods in a single call to the contract */ interface IMulticall { diff --git a/packages/interfaces/contracts/contracts/curation/ICuration.sol b/packages/interfaces/contracts/contracts/curation/ICuration.sol index cb6271991..8ca4d12d8 100644 --- a/packages/interfaces/contracts/contracts/curation/ICuration.sol +++ b/packages/interfaces/contracts/contracts/curation/ICuration.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; /** * @title Curation Interface - * @dev Interface for the Curation contract (and L2Curation too) + * @author Edge & Node + * @notice Interface for the Curation contract (and L2Curation too) */ interface ICuration { // -- Configuration -- diff --git a/packages/interfaces/contracts/contracts/curation/IGraphCurationToken.sol b/packages/interfaces/contracts/contracts/curation/IGraphCurationToken.sol index 644593f54..c710d074d 100644 --- a/packages/interfaces/contracts/contracts/curation/IGraphCurationToken.sol +++ b/packages/interfaces/contracts/contracts/curation/IGraphCurationToken.sol @@ -1,13 +1,32 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; +/** + * @title Graph Curation Token Interface + * @author Edge & Node + * @notice Interface for curation tokens that represent shares in subgraph curation pools + */ interface IGraphCurationToken is IERC20Upgradeable { + /** + * @notice Graph Curation Token Contract initializer. + * @param owner Address of the contract issuing this token + */ function initialize(address owner) external; + /** + * @notice Burn tokens from an address. + * @param account Address from where tokens will be burned + * @param amount Amount of tokens to burn + */ function burnFrom(address account, uint256 amount) external; + /** + * @notice Mint new tokens. + * @param to Address to send the newly minted tokens + * @param amount Amount of tokens to mint + */ function mint(address to, uint256 amount) external; } diff --git a/packages/interfaces/contracts/contracts/discovery/IGNS.sol b/packages/interfaces/contracts/contracts/discovery/IGNS.sol index 6c00ce694..d55c93521 100644 --- a/packages/interfaces/contracts/contracts/discovery/IGNS.sol +++ b/packages/interfaces/contracts/contracts/discovery/IGNS.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; /** * @title Interface for GNS + * @author Edge & Node + * @notice Interface for the Graph Name System (GNS) contract */ interface IGNS { // -- Pool -- @@ -12,6 +14,13 @@ interface IGNS { * @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) + * @param vSignal The token of the subgraph-deployment bonding curve + * @param nSignal The token of the subgraph bonding curve + * @param curatorNSignal Mapping of curator addresses to their name signal amounts + * @param subgraphDeploymentID The deployment ID this subgraph points to + * @param __DEPRECATED_reserveRatio Deprecated reserve ratio field + * @param disabled Whether the subgraph is disabled/deprecated + * @param withdrawableGRT Amount of GRT available for withdrawal after deprecation */ struct SubgraphData { uint256 vSignal; // The token of the subgraph-deployment bonding curve @@ -26,23 +35,14 @@ interface IGNS { /** * @dev The LegacySubgraphKey struct holds the account and sequence ID * used to generate subgraph IDs in legacy subgraphs. + * @param account The account that created the legacy subgraph + * @param accountSeqID The sequence ID for the account's subgraphs */ struct LegacySubgraphKey { address account; uint256 accountSeqID; } - // -- Events -- - - /** - * @dev Emitted when a subgraph version is updated. - */ - event SubgraphVersionUpdated( - uint256 indexed subgraphID, - bytes32 indexed subgraphDeploymentID, - bytes32 versionMetadata - ); - // -- Configuration -- /** @@ -127,7 +127,7 @@ interface IGNS { function burnSignal(uint256 subgraphID, uint256 nSignal, uint256 tokensOutMin) external; /** - * @notice Move subgraph signal from sender to recipient + * @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 @@ -169,7 +169,9 @@ interface IGNS { * @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 + * @return Amount of subgraph signal that can be bought + * @return Amount of version signal that can be bought + * @return Amount of curation tax */ function tokensToNSignal(uint256 subgraphID, uint256 tokensIn) external view returns (uint256, uint256, uint256); @@ -178,6 +180,7 @@ interface IGNS { * @param subgraphID Subgraph ID * @param nSignalIn Subgraph signal being exchanged for tokens * @return Amount of tokens returned for an amount of subgraph signal + * @return Amount of version signal returned */ function nSignalToTokens(uint256 subgraphID, uint256 nSignalIn) external view returns (uint256, uint256); diff --git a/packages/interfaces/contracts/contracts/discovery/IServiceRegistry.sol b/packages/interfaces/contracts/contracts/discovery/IServiceRegistry.sol index b3f5377c0..e3ef02807 100644 --- a/packages/interfaces/contracts/contracts/discovery/IServiceRegistry.sol +++ b/packages/interfaces/contracts/contracts/discovery/IServiceRegistry.sol @@ -1,20 +1,53 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +/** + * @title Service Registry Interface + * @author Edge & Node + * @notice Interface for the Service Registry contract that manages indexer service information + */ interface IServiceRegistry { + /** + * @dev Indexer service information + * @param url URL of the indexer service + * @param geohash Geohash of the indexer service location + */ struct IndexerService { string url; string geohash; } + /** + * @notice Register an indexer service + * @param url URL of the indexer service + * @param geohash Geohash of the indexer service location + */ function register(string calldata url, string calldata geohash) external; + /** + * @notice Register an indexer service + * @param indexer Address of the indexer + * @param url URL of the indexer service + * @param geohash Geohash of the indexer service location + */ function registerFor(address indexer, string calldata url, string calldata geohash) external; + /** + * @notice Unregister an indexer service + */ function unregister() external; + /** + * @notice Unregister an indexer service + * @param indexer Address of the indexer + */ function unregisterFor(address indexer) external; + /** + * @notice Return the registration status of an indexer service + * @param indexer Address of the indexer + * @return True if the indexer service is registered + */ function isRegistered(address indexer) external view returns (bool); } diff --git a/packages/interfaces/contracts/contracts/discovery/ISubgraphNFT.sol b/packages/interfaces/contracts/contracts/discovery/ISubgraphNFT.sol index 0f7d5a73d..c3be4216a 100644 --- a/packages/interfaces/contracts/contracts/discovery/ISubgraphNFT.sol +++ b/packages/interfaces/contracts/contracts/discovery/ISubgraphNFT.sol @@ -1,25 +1,67 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +/** + * @title Subgraph NFT Interface + * @author Edge & Node + * @notice Interface for the Subgraph NFT contract that represents subgraph ownership + */ interface ISubgraphNFT is IERC721 { // -- Config -- + /** + * @notice Set the minter allowed to perform actions on the NFT + * @dev Minter can mint, burn and update the metadata + * @param minter Address of the allowed minter + */ function setMinter(address minter) external; + /** + * @notice Set the token descriptor contract + * @dev Token descriptor can be zero. If set, it must be a contract + * @param tokenDescriptor Address of the contract that creates the NFT token URI + */ function setTokenDescriptor(address tokenDescriptor) external; + /** + * @notice Set the base URI + * @dev Can be set to empty + * @param baseURI Base URI to use to build the token URI + */ function setBaseURI(string memory baseURI) external; // -- Actions -- + /** + * @notice Mint `tokenId` and transfers it to `to` + * @dev `tokenId` must not exist and `to` cannot be the zero address + * @param to Address receiving the minted NFT + * @param tokenId ID of the NFT + */ function mint(address to, uint256 tokenId) external; + /** + * @notice Burn `tokenId` + * @dev The approval is cleared when the token is burned + * @param tokenId ID of the NFT + */ function burn(uint256 tokenId) external; + /** + * @notice Set the metadata for a subgraph represented by `tokenId` + * @dev `tokenId` must exist + * @param tokenId ID of the NFT + * @param subgraphMetadata IPFS hash for the metadata + */ function setSubgraphMetadata(uint256 tokenId, bytes32 subgraphMetadata) external; + /** + * @notice Returns the Uniform Resource Identifier (URI) for `tokenId` token + * @param tokenId ID of the NFT + * @return The URI for the token + */ function tokenURI(uint256 tokenId) external view returns (string memory); } diff --git a/packages/interfaces/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol b/packages/interfaces/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol index 429e22898..c7ea19ad4 100644 --- a/packages/interfaces/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol +++ b/packages/interfaces/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol @@ -1,8 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; -/// @title Describes subgraph NFT tokens via URI +/** + * @title Describes subgraph NFT tokens via URI + * @author Edge & Node + * @notice Interface for describing subgraph NFT tokens via URI + */ interface ISubgraphNFTDescriptor { /// @notice Produces the URI describing a particular token ID for a Subgraph /// @dev Note this URI may be data: URI with the JSON contents directly inlined diff --git a/packages/interfaces/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol b/packages/interfaces/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol index c4bdf1ba8..6a8258e31 100644 --- a/packages/interfaces/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol +++ b/packages/interfaces/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol @@ -1,9 +1,26 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +/** + * @title Ethereum DID Registry Interface + * @author Edge & Node + * @notice Interface for the Ethereum DID Registry contract + */ interface IEthereumDIDRegistry { + /** + * @notice Get the owner of an identity + * @param identity The identity address + * @return The address of the identity owner + */ function identityOwner(address identity) external view returns (address); + /** + * @notice Set an attribute for an identity + * @param identity The identity address + * @param name The attribute name + * @param value The attribute value + * @param validity The validity period in seconds + */ function setAttribute(address identity, bytes32 name, bytes calldata value, uint256 validity) external; } diff --git a/packages/interfaces/contracts/contracts/disputes/IDisputeManager.sol b/packages/interfaces/contracts/contracts/disputes/IDisputeManager.sol index eb86be5d0..e330f960d 100644 --- a/packages/interfaces/contracts/contracts/disputes/IDisputeManager.sol +++ b/packages/interfaces/contracts/contracts/disputes/IDisputeManager.sol @@ -1,17 +1,28 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.8.0 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; pragma abicoder v2; +/** + * @title Dispute Manager Interface + * @author Edge & Node + * @notice Interface for the Dispute Manager contract that handles indexing and query disputes + */ interface IDisputeManager { // -- Dispute -- + /** + * @dev Types of disputes that can be created + */ enum DisputeType { Null, IndexingDispute, QueryDispute } + /** + * @dev Status of a dispute + */ enum DisputeStatus { Null, Accepted, @@ -20,7 +31,15 @@ interface IDisputeManager { Pending } - // Disputes contain info necessary for the Arbitrator to verify and resolve + /** + * @dev Disputes contain info necessary for the Arbitrator to verify and resolve + * @param indexer Address of the indexer being disputed + * @param fisherman Address of the challenger creating the dispute + * @param deposit Amount of tokens staked as deposit + * @param relatedDisputeID ID of related dispute (for conflicting attestations) + * @param disputeType Type of dispute (Query or Indexing) + * @param status Current status of the dispute + */ struct Dispute { address indexer; address fisherman; @@ -32,14 +51,27 @@ interface IDisputeManager { // -- Attestation -- - // Receipt content sent from indexer in response to request + /** + * @dev Receipt content sent from indexer in response to request + * @param requestCID Content ID of the request + * @param responseCID Content ID of the response + * @param subgraphDeploymentID ID of the subgraph deployment + */ struct Receipt { bytes32 requestCID; bytes32 responseCID; bytes32 subgraphDeploymentID; } - // Attestation sent from indexer in response to a request + /** + * @dev Attestation sent from indexer in response to a request + * @param requestCID Content ID of the request + * @param responseCID Content ID of the response + * @param subgraphDeploymentID ID of the subgraph deployment + * @param r R component of the signature + * @param s S component of the signature + * @param v Recovery ID of the signature + */ struct Attestation { bytes32 requestCID; bytes32 responseCID; @@ -51,41 +83,121 @@ interface IDisputeManager { // -- Configuration -- + /** + * @dev Set the arbitrator address. + * @notice Update the arbitrator to `arbitrator` + * @param arbitrator The address of the arbitration contract or party + */ function setArbitrator(address arbitrator) external; + /** + * @dev Set the minimum deposit required to create a dispute. + * @notice Update the minimum deposit to `minimumDeposit` Graph Tokens + * @param minimumDeposit The minimum deposit in Graph Tokens + */ function setMinimumDeposit(uint256 minimumDeposit) external; + /** + * @dev Set the percent reward that the fisherman gets when slashing occurs. + * @notice Update the reward percentage to `percentage` + * @param percentage Reward as a percentage of indexer stake + */ function setFishermanRewardPercentage(uint32 percentage) external; + /** + * @notice Set the percentage used for slashing indexers. + * @param qryPercentage Percentage slashing for query disputes + * @param idxPercentage Percentage slashing for indexing disputes + */ function setSlashingPercentage(uint32 qryPercentage, uint32 idxPercentage) external; // -- Getters -- + /** + * @notice Check if a dispute has been created + * @param disputeID Dispute identifier + * @return True if the dispute exists + */ function isDisputeCreated(bytes32 disputeID) external view returns (bool); + /** + * @notice Encode a receipt into a hash for EIP-712 signature verification + * @param receipt The receipt to encode + * @return The encoded hash + */ function encodeHashReceipt(Receipt memory receipt) external view returns (bytes32); + /** + * @notice Check if two attestations are conflicting + * @param attestation1 First attestation + * @param attestation2 Second attestation + * @return True if attestations are conflicting + */ function areConflictingAttestations( Attestation memory attestation1, Attestation memory attestation2 ) external pure returns (bool); + /** + * @notice Get the indexer address from an attestation + * @param attestation The attestation to extract indexer from + * @return The indexer address + */ function getAttestationIndexer(Attestation memory attestation) external view returns (address); // -- Dispute -- + /** + * @notice Create a query dispute for the arbitrator to resolve. + * This function is called by a fisherman that will need to `deposit` at + * least `minimumDeposit` GRT tokens. + * @param attestationData Attestation bytes submitted by the fisherman + * @param deposit Amount of tokens staked as deposit + * @return The dispute ID + */ function createQueryDispute(bytes calldata attestationData, uint256 deposit) external returns (bytes32); + /** + * @notice Create query disputes for two conflicting attestations. + * A conflicting attestation is a proof presented by two different indexers + * where for the same request on a subgraph the response is different. + * For this type of dispute the submitter is not required to present a deposit + * as one of the attestation is considered to be right. + * Two linked disputes will be created and if the arbitrator resolve one, the other + * one will be automatically resolved. + * @param attestationData1 First attestation data submitted + * @param attestationData2 Second attestation data submitted + * @return First dispute ID + * @return Second dispute ID + */ function createQueryDisputeConflict( bytes calldata attestationData1, bytes calldata attestationData2 ) external returns (bytes32, bytes32); + /** + * @notice Create an indexing dispute + * @param allocationID Allocation ID being disputed + * @param deposit Deposit amount for the dispute + * @return The dispute ID + */ function createIndexingDispute(address allocationID, uint256 deposit) external returns (bytes32); + /** + * @notice Accept a dispute (arbitrator only) + * @param disputeID ID of the dispute to accept + */ function acceptDispute(bytes32 disputeID) external; + /** + * @notice Reject a dispute (arbitrator only) + * @param disputeID ID of the dispute to reject + */ function rejectDispute(bytes32 disputeID) external; + /** + * @notice Draw a dispute (arbitrator only) + * @param disputeID ID of the dispute to draw + */ function drawDispute(bytes32 disputeID) external; } diff --git a/packages/interfaces/contracts/contracts/epochs/IEpochManager.sol b/packages/interfaces/contracts/contracts/epochs/IEpochManager.sol index 06f3fd70a..8351e0933 100644 --- a/packages/interfaces/contracts/contracts/epochs/IEpochManager.sol +++ b/packages/interfaces/contracts/contracts/epochs/IEpochManager.sol @@ -1,31 +1,78 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +/** + * @title Epoch Manager Interface + * @author Edge & Node + * @notice Interface for the Epoch Manager contract that handles protocol epochs + */ interface IEpochManager { // -- Configuration -- + /** + * @notice Set epoch length to `epochLength` blocks + * @param epochLength Epoch length in blocks + */ function setEpochLength(uint256 epochLength) external; // -- Epochs + /** + * @dev Run a new epoch, should be called once at the start of any epoch. + * @notice Perform state changes for the current epoch + */ function runEpoch() external; // -- Getters -- + /** + * @notice Check if the current epoch has been run + * @return True if current epoch has been run, false otherwise + */ function isCurrentEpochRun() external view returns (bool); + /** + * @notice Get the current block number + * @return Current block number + */ function blockNum() external view returns (uint256); - function blockHash(uint256 block) external view returns (bytes32); + /** + * @notice Get the hash of a specific block + * @param blockNumber Block number to get hash for + * @return Block hash + */ + function blockHash(uint256 blockNumber) external view returns (bytes32); + /** + * @notice Get the current epoch number + * @return Current epoch number + */ function currentEpoch() external view returns (uint256); + /** + * @notice Get the block number when the current epoch started + * @return Block number of current epoch start + */ function currentEpochBlock() external view returns (uint256); + /** + * @notice Get the number of blocks since the current epoch started + * @return Number of blocks since current epoch start + */ function currentEpochBlockSinceStart() external view returns (uint256); + /** + * @notice Get the number of epochs since a given epoch + * @param epoch Epoch to calculate from + * @return Number of epochs since the given epoch + */ function epochsSince(uint256 epoch) external view returns (uint256); + /** + * @notice Get the number of epochs since the last epoch length update + * @return Number of epochs since last update + */ function epochsSinceUpdate() external view returns (uint256); } diff --git a/packages/interfaces/contracts/contracts/gateway/ICallhookReceiver.sol b/packages/interfaces/contracts/contracts/gateway/ICallhookReceiver.sol index 86bc654a0..6e6958352 100644 --- a/packages/interfaces/contracts/contracts/gateway/ICallhookReceiver.sol +++ b/packages/interfaces/contracts/contracts/gateway/ICallhookReceiver.sol @@ -2,12 +2,18 @@ /** * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge - * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must + * @author Edge & Node + * @notice Any contract that can receive a callhook on L2, sent through the bridge from L1, must * be allowlisted by the governor, but also implement this interface that contains * the function that will actually be called by the L2GraphTokenGateway. */ -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.3 || ^0.8.0; +/** + * @title Callhook Receiver Interface + * @author Edge & Node + * @notice Interface for contracts that can receive tokens with callhook from the bridge + */ interface ICallhookReceiver { /** * @notice Receive tokens with a callhook from the bridge diff --git a/packages/interfaces/contracts/contracts/governance/IController.sol b/packages/interfaces/contracts/contracts/governance/IController.sol index 2f6d3b6b7..6d786e165 100644 --- a/packages/interfaces/contracts/contracts/governance/IController.sol +++ b/packages/interfaces/contracts/contracts/governance/IController.sol @@ -1,29 +1,79 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +/** + * @title Controller Interface + * @author Edge & Node + * @notice Interface for the Controller contract that manages protocol governance and contract registry + */ interface IController { + /** + * @notice Return the governor address + * @return The governor address + */ function getGovernor() external view returns (address); // -- Registry -- + /** + * @notice Register contract id and mapped address + * @param id Contract id (keccak256 hash of contract name) + * @param contractAddress Contract address + */ function setContractProxy(bytes32 id, address contractAddress) external; + /** + * @notice Unregister a contract address + * @param id Contract id (keccak256 hash of contract name) + */ function unsetContractProxy(bytes32 id) external; + /** + * @notice Update contract's controller + * @param id Contract id (keccak256 hash of contract name) + * @param controller Controller address + */ function updateController(bytes32 id, address controller) external; + /** + * @notice Get contract proxy address by its id + * @param id Contract id + * @return Address of the proxy contract for the provided id + */ function getContractProxy(bytes32 id) external view returns (address); // -- Pausing -- - function setPartialPaused(bool partialPaused) external; + /** + * @notice Change the partial paused state of the contract + * Partial pause is intended as a partial pause of the protocol + * @param partialPause True if the contracts should be (partially) paused, false otherwise + */ + function setPartialPaused(bool partialPause) external; - function setPaused(bool paused) external; + /** + * @notice Change the paused state of the contract + * Full pause most of protocol functions + * @param pause True if the contracts should be paused, false otherwise + */ + function setPaused(bool pause) external; + /** + * @notice Change the Pause Guardian + * @param newPauseGuardian The address of the new Pause Guardian + */ function setPauseGuardian(address newPauseGuardian) external; + /** + * @notice Return whether the protocol is paused + * @return True if the protocol is paused + */ function paused() external view returns (bool); + /** + * @notice Return whether the protocol is partially paused + * @return True if the protocol is partially paused + */ function partialPaused() external view returns (bool); } diff --git a/packages/interfaces/contracts/contracts/governance/IGoverned.sol b/packages/interfaces/contracts/contracts/governance/IGoverned.sol index 200f74ecf..c7688a6cd 100644 --- a/packages/interfaces/contracts/contracts/governance/IGoverned.sol +++ b/packages/interfaces/contracts/contracts/governance/IGoverned.sol @@ -1,15 +1,24 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; /** * @title IGoverned - * @dev Interface for the Governed contract. + * @author Edge & Node + * @notice Interface for governed contracts */ interface IGoverned { // -- State getters -- + /** + * @notice Get the current governor address + * @return The address of the current governor + */ function governor() external view returns (address); + /** + * @notice Get the pending governor address + * @return The address of the pending governor + */ function pendingGovernor() external view returns (address); // -- External functions -- @@ -27,7 +36,17 @@ interface IGoverned { // -- Events -- + /** + * @notice Emitted when a new pending governor is set + * @param from The address of the current governor + * @param to The address of the new pending governor + */ event NewPendingOwnership(address indexed from, address indexed to); + /** + * @notice Emitted when governance is transferred to a new governor + * @param from The address of the previous governor + * @param to The address of the new governor + */ event NewOwnership(address indexed from, address indexed to); } diff --git a/packages/interfaces/contracts/contracts/governance/IManaged.sol b/packages/interfaces/contracts/contracts/governance/IManaged.sol index 9bfe57083..d45dacaee 100644 --- a/packages/interfaces/contracts/contracts/governance/IManaged.sol +++ b/packages/interfaces/contracts/contracts/governance/IManaged.sol @@ -1,20 +1,21 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; import { IController } from "./IController.sol"; /** * @title Managed Interface - * @dev Interface for contracts that can be managed by a controller. + * @author Edge & Node + * @notice 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 + * @param newController Address of the new controller */ - function setController(address controller) external; + function setController(address newController) external; /** * @notice Sync protocol contract addresses from the Controller registry diff --git a/packages/interfaces/contracts/contracts/l2/curation/IL2Curation.sol b/packages/interfaces/contracts/contracts/l2/curation/IL2Curation.sol index 18f6882cc..889f7a852 100644 --- a/packages/interfaces/contracts/contracts/l2/curation/IL2Curation.sol +++ b/packages/interfaces/contracts/contracts/l2/curation/IL2Curation.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; /** * @title Interface of the L2 Curation contract. + * @author Edge & Node + * @notice Interface for the L2 Curation contract that handles curation on Layer 2 */ interface IL2Curation { /** diff --git a/packages/interfaces/contracts/contracts/l2/discovery/IL2GNS.sol b/packages/interfaces/contracts/contracts/l2/discovery/IL2GNS.sol index 12a1aeec9..5b60fc1a7 100644 --- a/packages/interfaces/contracts/contracts/l2/discovery/IL2GNS.sol +++ b/packages/interfaces/contracts/contracts/l2/discovery/IL2GNS.sol @@ -1,13 +1,20 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; import { ICallhookReceiver } from "../../gateway/ICallhookReceiver.sol"; /** * @title Interface for the L2GNS contract. + * @author Edge & Node + * @notice Interface for the L2 Graph Name System (GNS) contract */ interface IL2GNS is ICallhookReceiver { + /** + * @dev Message codes for L1 to L2 communication + * @param RECEIVE_SUBGRAPH_CODE Code for receiving subgraph transfers + * @param RECEIVE_CURATOR_BALANCE_CODE Code for receiving curator balance transfers + */ enum L1MessageCodes { RECEIVE_SUBGRAPH_CODE, RECEIVE_CURATOR_BALANCE_CODE @@ -16,6 +23,10 @@ interface IL2GNS is ICallhookReceiver { /** * @dev The SubgraphL2TransferData struct holds information * about a subgraph related to its transfer from L1 to L2. + * @param tokens GRT that will be sent to L2 to mint signal + * @param curatorBalanceClaimed True for curators whose balance has been claimed in L2 + * @param l2Done Transfer finished on L2 side + * @param subgraphReceivedOnL2BlockNumber Block number when the subgraph was received on L2 */ struct SubgraphL2TransferData { uint256 tokens; // GRT that will be sent to L2 to mint signal diff --git a/packages/interfaces/contracts/contracts/l2/gateway/IL2GraphTokenGateway.sol b/packages/interfaces/contracts/contracts/l2/gateway/IL2GraphTokenGateway.sol index b1e088212..b6e6df745 100644 --- a/packages/interfaces/contracts/contracts/l2/gateway/IL2GraphTokenGateway.sol +++ b/packages/interfaces/contracts/contracts/l2/gateway/IL2GraphTokenGateway.sol @@ -1,7 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events + +/** + * @title IL2GraphTokenGateway + * @author Edge & Node + * @notice Interface for the L2 Graph Token Gateway contract that handles token bridging on L2 + */ interface IL2GraphTokenGateway { // Structs struct OutboundCalldata { @@ -10,7 +18,24 @@ interface IL2GraphTokenGateway { } // Events + /** + * @notice Emitted when a deposit from L1 is finalized on L2 + * @param l1Token The L1 token address + * @param from The sender address on L1 + * @param to The recipient address on L2 + * @param amount The amount of tokens deposited + */ event DepositFinalized(address indexed l1Token, address indexed from, address indexed to, uint256 amount); + + /** + * @notice Emitted when a withdrawal from L2 to L1 is initiated + * @param l1Token The L1 token address + * @param from The sender address on L2 + * @param to The recipient address on L1 + * @param l2ToL1Id The L2 to L1 message ID + * @param exitNum The exit number + * @param amount The amount of tokens withdrawn + */ event WithdrawalInitiated( address l1Token, address indexed from, @@ -19,19 +44,58 @@ interface IL2GraphTokenGateway { uint256 exitNum, uint256 amount ); + + /** + * @notice Emitted when the L2 router address is set + * @param l2Router The new L2 router address + */ event L2RouterSet(address l2Router); + + /** + * @notice Emitted when the L1 token address is set + * @param l1GRT The L1 GRT token address + */ event L1TokenAddressSet(address l1GRT); + + /** + * @notice Emitted when the L1 counterpart address is set + * @param l1Counterpart The L1 counterpart gateway address + */ event L1CounterpartAddressSet(address l1Counterpart); // Functions + /** + * @notice Initialize the gateway contract + * @param controller The controller contract address + */ function initialize(address controller) external; + /** + * @notice Set the L2 router address + * @param l2Router The L2 router contract address + */ function setL2Router(address l2Router) external; + /** + * @notice Set the L1 token address + * @param l1GRT The L1 GRT token contract address + */ function setL1TokenAddress(address l1GRT) external; + /** + * @notice Set the L1 counterpart gateway address + * @param l1Counterpart The L1 counterpart gateway contract address + */ function setL1CounterpartAddress(address l1Counterpart) external; + /** + * @notice Transfer tokens from L2 to L1 + * @param l1Token The L1 token address + * @param to The recipient address on L1 + * @param amount The amount of tokens to transfer + * @param data Additional data for the transfer + * @return The encoded outbound transfer data + */ function outboundTransfer( address l1Token, address to, @@ -39,6 +103,14 @@ interface IL2GraphTokenGateway { bytes calldata data ) external returns (bytes memory); + /** + * @notice Finalize an inbound transfer from L1 to L2 + * @param l1Token The L1 token address + * @param from The sender address on L1 + * @param to The recipient address on L2 + * @param amount The amount of tokens to transfer + * @param data Additional data for the transfer + */ function finalizeInboundTransfer( address l1Token, address from, @@ -47,6 +119,16 @@ interface IL2GraphTokenGateway { bytes calldata data ) external payable; + /** + * @notice Transfer tokens from L2 to L1 (overloaded version with unused parameters) + * @param l1Token The L1 token address + * @param to The recipient address on L1 + * @param amount The amount of tokens to transfer + * @param unused1 Unused parameter for compatibility + * @param unused2 Unused parameter for compatibility + * @param data Additional data for the transfer + * @return The encoded outbound transfer data + */ function outboundTransfer( address l1Token, address to, @@ -56,8 +138,22 @@ interface IL2GraphTokenGateway { bytes calldata data ) external payable returns (bytes memory); + /** + * @notice Calculate the L2 token address for a given L1 token + * @param l1ERC20 The L1 token address + * @return The corresponding L2 token address + */ function calculateL2TokenAddress(address l1ERC20) external view returns (address); + /** + * @notice Get the encoded calldata for an outbound transfer + * @param token The token address + * @param from The sender address + * @param to The recipient address + * @param amount The amount of tokens + * @param data Additional transfer data + * @return The encoded calldata + */ function getOutboundCalldata( address token, address from, diff --git a/packages/interfaces/contracts/contracts/l2/staking/IL2Staking.sol b/packages/interfaces/contracts/contracts/l2/staking/IL2Staking.sol index 0b1718571..4fa87e294 100644 --- a/packages/interfaces/contracts/contracts/l2/staking/IL2Staking.sol +++ b/packages/interfaces/contracts/contracts/l2/staking/IL2Staking.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; pragma abicoder v2; import { IStaking } from "../../staking/IStaking.sol"; @@ -9,6 +9,7 @@ import { IL2StakingTypes } from "./IL2StakingTypes.sol"; /** * @title Interface for the L2 Staking contract + * @author Edge & Node * @notice This is the interface that should be used when interacting with the L2 Staking contract. * It extends the IStaking interface with the functions that are specific to L2, adding the callhook receiver * to receive transferred stake and delegation from L1. diff --git a/packages/interfaces/contracts/contracts/l2/staking/IL2StakingBase.sol b/packages/interfaces/contracts/contracts/l2/staking/IL2StakingBase.sol index f5c33c2d0..0eaff2b90 100644 --- a/packages/interfaces/contracts/contracts/l2/staking/IL2StakingBase.sol +++ b/packages/interfaces/contracts/contracts/l2/staking/IL2StakingBase.sol @@ -1,14 +1,24 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events import { ICallhookReceiver } from "../../gateway/ICallhookReceiver.sol"; /** * @title Base interface for the L2Staking contract. + * @author Edge & Node * @notice This interface is used to define the callhook receiver interface that is implemented by L2Staking. * @dev Note it includes only the L2-specific functionality, not the full IStaking interface. */ interface IL2StakingBase is ICallhookReceiver { + /** + * @notice Emitted when transferred delegation is returned to a delegator + * @param indexer Address of the indexer + * @param delegator Address of the delegator + * @param amount Amount of delegation returned + */ event TransferredDelegationReturnedToDelegator(address indexed indexer, address indexed delegator, uint256 amount); } diff --git a/packages/interfaces/contracts/contracts/l2/staking/IL2StakingTypes.sol b/packages/interfaces/contracts/contracts/l2/staking/IL2StakingTypes.sol index 500694e89..672f92513 100644 --- a/packages/interfaces/contracts/contracts/l2/staking/IL2StakingTypes.sol +++ b/packages/interfaces/contracts/contracts/l2/staking/IL2StakingTypes.sol @@ -1,7 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +/** + * @title IL2StakingTypes + * @author Edge & Node + * @notice Interface defining types and enums used by L2 staking contracts + */ interface IL2StakingTypes { /// @dev Message codes for the L1 -> L2 bridge callhook enum L1MessageCodes { diff --git a/packages/interfaces/contracts/contracts/l2/token/IL2GraphToken.sol b/packages/interfaces/contracts/contracts/l2/token/IL2GraphToken.sol index 92b12946d..b12788a5d 100644 --- a/packages/interfaces/contracts/contracts/l2/token/IL2GraphToken.sol +++ b/packages/interfaces/contracts/contracts/l2/token/IL2GraphToken.sol @@ -1,20 +1,63 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events import { IGraphToken } from "../../token/IGraphToken.sol"; +/** + * @title IL2GraphToken + * @author Edge & Node + * @notice Interface for the L2 Graph Token contract that extends IGraphToken with L2-specific functionality + */ interface IL2GraphToken is IGraphToken { // Events + /** + * @notice Emitted when tokens are minted through the bridge + * @param account The account that received the minted tokens + * @param amount The amount of tokens minted + */ event BridgeMinted(address indexed account, uint256 amount); + + /** + * @notice Emitted when tokens are burned through the bridge + * @param account The account from which tokens were burned + * @param amount The amount of tokens burned + */ event BridgeBurned(address indexed account, uint256 amount); + + /** + * @notice Emitted when the gateway address is set + * @param gateway The new gateway address + */ event GatewaySet(address gateway); + + /** + * @notice Emitted when the L1 address is set + * @param l1Address The new L1 address + */ event L1AddressSet(address l1Address); // Public state variables (view functions) + /** + * @notice Get the gateway contract address + * @return The address of the gateway contract + */ function gateway() external view returns (address); + + /** + * @notice Get the L1 contract address + * @return The address of the L1 contract + */ function l1Address() external view returns (address); // Functions + + /** + * @notice Initialize the L2 token contract + * @param owner The owner address for the contract + */ function initialize(address owner) external; /** diff --git a/packages/interfaces/contracts/contracts/rewards/ILegacyRewardsManager.sol b/packages/interfaces/contracts/contracts/rewards/ILegacyRewardsManager.sol index 7ea628e20..0414b55cb 100644 --- a/packages/interfaces/contracts/contracts/rewards/ILegacyRewardsManager.sol +++ b/packages/interfaces/contracts/contracts/rewards/ILegacyRewardsManager.sol @@ -1,7 +1,17 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +/** + * @title ILegacyRewardsManager + * @author Edge & Node + * @notice Interface for the legacy rewards manager contract + */ interface ILegacyRewardsManager { + /** + * @notice Get the accumulated rewards for a given allocation + * @param allocationID The allocation identifier + * @return The amount of accumulated rewards + */ function getRewards(address allocationID) external view returns (uint256); } diff --git a/packages/interfaces/contracts/contracts/rewards/IRewardsIssuer.sol b/packages/interfaces/contracts/contracts/rewards/IRewardsIssuer.sol index 0f1ed9d8f..34e398b2a 100644 --- a/packages/interfaces/contracts/contracts/rewards/IRewardsIssuer.sol +++ b/packages/interfaces/contracts/contracts/rewards/IRewardsIssuer.sol @@ -1,10 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +/** + * @title Rewards Issuer Interface + * @author Edge & Node + * @notice Interface for contracts that issue rewards based on allocation data + */ interface IRewardsIssuer { /** - * @dev Get allocation data to calculate rewards issuance + * @notice Get allocation data to calculate rewards issuance * * @param allocationId The allocation Id * @return isActive Whether the allocation is active or not diff --git a/packages/interfaces/contracts/contracts/rewards/IRewardsManager.sol b/packages/interfaces/contracts/contracts/rewards/IRewardsManager.sol index 32b618f60..72a73e19b 100644 --- a/packages/interfaces/contracts/contracts/rewards/IRewardsManager.sol +++ b/packages/interfaces/contracts/contracts/rewards/IRewardsManager.sol @@ -1,10 +1,19 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +/** + * @title IRewardsManager + * @author Edge & Node + * @notice Interface for the RewardsManager contract that handles reward distribution + */ interface IRewardsManager { /** - * @dev Stores accumulated rewards and snapshots related to a particular SubgraphDeployment. + * @dev Stores accumulated rewards and snapshots related to a particular SubgraphDeployment + * @param accRewardsForSubgraph Accumulated rewards for the subgraph + * @param accRewardsForSubgraphSnapshot Snapshot of accumulated rewards for the subgraph + * @param accRewardsPerSignalSnapshot Snapshot of accumulated rewards per signal + * @param accRewardsPerAllocatedToken Accumulated rewards per allocated token */ struct Subgraph { uint256 accRewardsForSubgraph; @@ -15,43 +24,128 @@ interface IRewardsManager { // -- Config -- + /** + * @notice Set the issuance per block for rewards distribution + * @param issuancePerBlock The amount of tokens to issue per block + */ function setIssuancePerBlock(uint256 issuancePerBlock) external; + /** + * @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; + /** + * @notice Set the subgraph service address + * @param subgraphService Address of the subgraph service contract + */ function setSubgraphService(address subgraphService) external; // -- Denylist -- + /** + * @notice Set the subgraph availability oracle address + * @param subgraphAvailabilityOracle The address of the subgraph availability oracle + */ function setSubgraphAvailabilityOracle(address subgraphAvailabilityOracle) external; + /** + * @notice Set the denied status for a subgraph deployment + * @param subgraphDeploymentID The subgraph deployment ID + * @param deny True to deny, false to allow + */ function setDenied(bytes32 subgraphDeploymentID, bool deny) external; + /** + * @notice Check if a subgraph deployment is denied + * @param subgraphDeploymentID The subgraph deployment ID to check + * @return True if the subgraph is denied, false otherwise + */ function isDenied(bytes32 subgraphDeploymentID) external view returns (bool); // -- Getters -- + /** + * @notice Gets the issuance of rewards per signal since last updated + * @return newly accrued rewards per signal since last update + */ function getNewRewardsPerSignal() external view returns (uint256); + /** + * @notice Gets the currently accumulated rewards per signal + * @return Currently accumulated rewards per signal + */ function getAccRewardsPerSignal() external view returns (uint256); + /** + * @notice Get the accumulated rewards for a specific subgraph + * @param subgraphDeploymentID The subgraph deployment ID + * @return The accumulated rewards for the subgraph + */ function getAccRewardsForSubgraph(bytes32 subgraphDeploymentID) external view returns (uint256); + /** + * @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) external view returns (uint256, uint256); + /** + * @notice Calculate current rewards for a given allocation on demand + * @param rewardsIssuer The rewards issuer contract + * @param allocationID Allocation + * @return Rewards amount for an allocation + */ function getRewards(address rewardsIssuer, address allocationID) external view returns (uint256); + /** + * @notice Calculate rewards based on tokens and accumulated rewards per allocated token + * @param tokens The number of tokens allocated + * @param accRewardsPerAllocatedToken The accumulated rewards per allocated token + * @return The calculated rewards amount + */ function calcRewards(uint256 tokens, uint256 accRewardsPerAllocatedToken) external pure returns (uint256); // -- 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() external returns (uint256); + /** + * @notice Pull rewards from the contract for a particular allocation + * @dev 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 returns (uint256); // -- Hooks -- + /** + * @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 returns (uint256); + /** + * @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) external returns (uint256); } diff --git a/packages/interfaces/contracts/contracts/staking/IL1GraphTokenLockTransferTool.sol b/packages/interfaces/contracts/contracts/staking/IL1GraphTokenLockTransferTool.sol index aca3b0ffd..bbf5ea12c 100644 --- a/packages/interfaces/contracts/contracts/staking/IL1GraphTokenLockTransferTool.sol +++ b/packages/interfaces/contracts/contracts/staking/IL1GraphTokenLockTransferTool.sol @@ -1,11 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; pragma abicoder v2; /** * @title Interface for the L1GraphTokenLockTransferTool contract - * @dev This interface defines the function to get the L2 wallet address for a given L1 token lock wallet. + * @author Edge & Node + * @notice This interface defines the function to get the L2 wallet address for a given L1 token lock wallet. * The Transfer Tool contract is implemented in the token-distribution repo: https://github.com/graphprotocol/token-distribution/pull/64 * and is only included here to provide support in L1Staking for the transfer of stake and delegation * owned by token lock contracts. See GIP-0046 for details: https://forum.thegraph.com/t/4023 diff --git a/packages/interfaces/contracts/contracts/staking/IL1Staking.sol b/packages/interfaces/contracts/contracts/staking/IL1Staking.sol index fd7859220..b29686af2 100644 --- a/packages/interfaces/contracts/contracts/staking/IL1Staking.sol +++ b/packages/interfaces/contracts/contracts/staking/IL1Staking.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; pragma abicoder v2; import { IStaking } from "./IStaking.sol"; @@ -8,6 +8,7 @@ import { IL1StakingBase } from "./IL1StakingBase.sol"; /** * @title Interface for the L1 Staking contract + * @author Edge & Node * @notice This is the interface that should be used when interacting with the L1 Staking contract. * It extends the IStaking interface with the functions that are specific to L1, adding the transfer tools * to send stake and delegation to L2. diff --git a/packages/interfaces/contracts/contracts/staking/IL1StakingBase.sol b/packages/interfaces/contracts/contracts/staking/IL1StakingBase.sol index 9ed037258..3443a39fd 100644 --- a/packages/interfaces/contracts/contracts/staking/IL1StakingBase.sol +++ b/packages/interfaces/contracts/contracts/staking/IL1StakingBase.sol @@ -1,25 +1,41 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events + import { IL1GraphTokenLockTransferTool } from "./IL1GraphTokenLockTransferTool.sol"; /** * @title Base interface for the L1Staking contract. + * @author Edge & Node * @notice This interface is used to define the transfer tools that are implemented in L1Staking. * @dev Note it includes only the L1-specific functionality, not the full IStaking interface. */ interface IL1StakingBase { - /// @dev Emitted when an indexer transfers their stake to L2. - /// This can happen several times as indexers can transfer partial stake. + /** + * @notice Emitted when an indexer transfers their stake to L2. + * This can happen several times as indexers can transfer partial stake. + * @param indexer Address of the indexer on L1 + * @param l2Indexer Address of the indexer on L2 + * @param transferredStakeTokens Amount of stake tokens transferred + */ event IndexerStakeTransferredToL2( address indexed indexer, address indexed l2Indexer, uint256 transferredStakeTokens ); - /// @dev Emitted when a delegator transfers their delegation to L2 + /** + * @notice Emitted when a delegator transfers their delegation to L2 + * @param delegator Address of the delegator on L1 + * @param l2Delegator Address of the delegator on L2 + * @param indexer Address of the indexer on L1 + * @param l2Indexer Address of the indexer on L2 + * @param transferredDelegationTokens Amount of delegation tokens transferred + */ event DelegationTransferredToL2( address indexed delegator, address indexed l2Delegator, @@ -28,10 +44,17 @@ interface IL1StakingBase { uint256 transferredDelegationTokens ); - /// @dev Emitted when the L1GraphTokenLockTransferTool is set + /** + * @notice Emitted when the L1GraphTokenLockTransferTool is set + * @param l1GraphTokenLockTransferTool Address of the L1GraphTokenLockTransferTool contract + */ event L1GraphTokenLockTransferToolSet(address l1GraphTokenLockTransferTool); - /// @dev Emitted when a delegator unlocks their tokens ahead of time because the indexer has transferred to L2 + /** + * @notice Emitted when a delegator unlocks their tokens ahead of time because the indexer has transferred to L2 + * @param indexer Address of the indexer that transferred to L2 + * @param delegator Address of the delegator unlocking their tokens + */ event StakeDelegatedUnlockedDueToL2Transfer(address indexed indexer, address indexed delegator); /** diff --git a/packages/interfaces/contracts/contracts/staking/IStaking.sol b/packages/interfaces/contracts/contracts/staking/IStaking.sol index c18e382b3..c644009b6 100644 --- a/packages/interfaces/contracts/contracts/staking/IStaking.sol +++ b/packages/interfaces/contracts/contracts/staking/IStaking.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; pragma abicoder v2; import { IStakingBase } from "./IStakingBase.sol"; @@ -10,6 +10,7 @@ import { IManaged } from "../governance/IManaged.sol"; /** * @title Interface for the Staking contract + * @author Edge & Node * @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 diff --git a/packages/interfaces/contracts/contracts/staking/IStakingBase.sol b/packages/interfaces/contracts/contracts/staking/IStakingBase.sol index d7728d049..6af61c077 100644 --- a/packages/interfaces/contracts/contracts/staking/IStakingBase.sol +++ b/packages/interfaces/contracts/contracts/staking/IStakingBase.sol @@ -1,12 +1,17 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events + import { IStakingData } from "./IStakingData.sol"; /** * @title Base interface for the Staking contract. + * @author Edge & Node + * @notice 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 @@ -15,25 +20,38 @@ import { IStakingData } from "./IStakingData.sol"; */ interface IStakingBase is IStakingData { /** - * @dev Emitted when `indexer` stakes `tokens` amount. + * @notice Emitted when `indexer` stakes `tokens` amount. + * @param indexer Address of the indexer + * @param tokens Amount of tokens staked */ event StakeDeposited(address indexed indexer, uint256 tokens); /** - * @dev Emitted when `indexer` unstaked and locked `tokens` amount until `until` block. + * @notice Emitted when `indexer` unstaked and locked `tokens` amount until `until` block. + * @param indexer Address of the indexer + * @param tokens Amount of tokens locked + * @param until Block number until which tokens are locked */ event StakeLocked(address indexed indexer, uint256 tokens, uint256 until); /** - * @dev Emitted when `indexer` withdrew `tokens` staked. + * @notice Emitted when `indexer` withdrew `tokens` staked. + * @param indexer Address of the indexer + * @param tokens Amount of tokens withdrawn */ event StakeWithdrawn(address indexed indexer, uint256 tokens); /** - * @dev Emitted when `indexer` allocated `tokens` amount to `subgraphDeploymentID` + * @notice 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. + * @param indexer Address of the indexer + * @param subgraphDeploymentID Subgraph deployment ID + * @param epoch Epoch when allocation was created + * @param tokens Amount of tokens allocated + * @param allocationID Allocation identifier + * @param metadata IPFS hash for additional allocation information */ event AllocationCreated( address indexed indexer, @@ -45,10 +63,18 @@ interface IStakingBase is IStakingData { ); /** - * @dev Emitted when `indexer` close an allocation in `epoch` for `allocationID`. + * @notice 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. + * @param indexer Address of the indexer + * @param subgraphDeploymentID Subgraph deployment ID + * @param epoch Epoch when allocation was closed + * @param tokens Amount of tokens unallocated + * @param allocationID Allocation identifier + * @param sender Address that closed the allocation + * @param poi Proof of indexing submitted + * @param isPublic True if closed by someone other than the indexer */ event AllocationClosed( address indexed indexer, @@ -62,12 +88,23 @@ interface IStakingBase is IStakingData { ); /** - * @dev Emitted when `indexer` collects a rebate on `subgraphDeploymentID` for `allocationID`. + * @notice 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. + * @param assetHolder Address providing the rebate tokens + * @param indexer Address of the indexer collecting the rebate + * @param subgraphDeploymentID Subgraph deployment ID + * @param allocationID Allocation identifier + * @param epoch Epoch when rebate was collected + * @param tokens Total amount of tokens in the rebate + * @param protocolTax Amount burned as protocol tax + * @param curationFees Amount distributed to curators + * @param queryFees Amount available for rebate after fees + * @param queryRebates Amount distributed to the indexer + * @param delegationRewards Amount distributed to delegators */ event RebateCollected( address assetHolder, @@ -84,7 +121,11 @@ interface IStakingBase is IStakingData { ); /** - * @dev Emitted when `indexer` update the delegation parameters for its delegation pool. + * @notice Emitted when `indexer` update the delegation parameters for its delegation pool. + * @param indexer Address of the indexer + * @param indexingRewardCut Percentage of indexing rewards left for the indexer + * @param queryFeeCut Percentage of query fees left for the indexer + * @param __DEPRECATED_cooldownBlocks Deprecated parameter (no longer used) */ event DelegationParametersUpdated( address indexed indexer, @@ -94,18 +135,24 @@ interface IStakingBase is IStakingData { ); /** - * @dev Emitted when `indexer` set `operator` access. + * @notice Emitted when `indexer` set `operator` access. + * @param indexer Address of the indexer + * @param operator Address of the operator + * @param allowed Whether the operator is authorized */ event SetOperator(address indexed indexer, address indexed operator, bool allowed); /** - * @dev Emitted when `indexer` set an address to receive rewards. + * @notice Emitted when `indexer` set an address to receive rewards. + * @param indexer Address of the indexer + * @param destination 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 + * @notice Emitted when `extensionImpl` was set as the address of the StakingExtension contract * to which extended functionality is delegated. + * @param extensionImpl Address of the StakingExtension implementation */ event ExtensionImplementationSet(address indexed extensionImpl); @@ -260,12 +307,9 @@ interface IStakingBase is IStakingData { * @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 + * @param cooldownBlocks Deprecated cooldown blocks parameter (no longer used) */ - function setDelegationParameters( - uint32 indexingRewardCut, - uint32 queryFeeCut, - uint32 // cooldownBlocks, deprecated - ) external; + function setDelegationParameters(uint32 indexingRewardCut, uint32 queryFeeCut, uint32 cooldownBlocks) external; /** * @notice Allocate available tokens to a subgraph deployment. @@ -362,18 +406,29 @@ interface IStakingBase is IStakingData { function getAllocation(address allocationID) external view returns (Allocation memory); /** + * @notice Get the allocation data for the rewards manager * @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. + * @param allocationID The allocation ID + * @return active Whether the allocation is active + * @return indexer The indexer address + * @return subgraphDeploymentID The subgraph deployment ID + * @return tokens The allocated tokens + * @return createdAtEpoch The epoch when allocation was created + * @return closedAtEpoch The epoch when allocation was closed */ function getAllocationData( address allocationID ) external view returns (bool, address, bytes32, uint256, uint256, uint256); /** + * @notice Get the allocation active status for the rewards manager * @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. + * @param allocationID The allocation identifier + * @return True if the allocation is active, false otherwise */ function isActiveAllocation(address allocationID) external view returns (bool); diff --git a/packages/interfaces/contracts/contracts/staking/IStakingData.sol b/packages/interfaces/contracts/contracts/staking/IStakingData.sol index 7db4d0ca1..59acd96ff 100644 --- a/packages/interfaces/contracts/contracts/staking/IStakingData.sol +++ b/packages/interfaces/contracts/contracts/staking/IStakingData.sol @@ -1,15 +1,25 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; /** * @title Staking Data interface - * @dev This interface defines some structures used by the Staking contract. + * @author Edge & Node + * @notice 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() + * @param indexer Address of the indexer that owns the allocation + * @param subgraphDeploymentID Subgraph deployment ID being allocated to + * @param tokens Tokens allocated to a SubgraphDeployment + * @param createdAtEpoch Epoch when it was created + * @param closedAtEpoch Epoch when it was closed + * @param collectedFees Collected fees for the allocation + * @param __DEPRECATED_effectiveAllocation Deprecated field for effective allocation + * @param accRewardsPerAllocatedToken Snapshot used for reward calc + * @param distributedRebates Collected rebates that have been rebated */ struct Allocation { address indexer; @@ -27,6 +37,13 @@ interface IStakingData { /** * @dev Delegation pool information. One per indexer. + * @param __DEPRECATED_cooldownBlocks Deprecated field for cooldown blocks + * @param indexingRewardCut Indexing reward cut in PPM + * @param queryFeeCut Query fee cut in PPM + * @param updatedAtBlock Block when the pool was last updated + * @param tokens Total tokens as pool reserves + * @param shares Total shares minted in the pool + * @param delegators Mapping of delegator => Delegation */ struct DelegationPool { uint32 __DEPRECATED_cooldownBlocks; // solhint-disable-line var-name-mixedcase @@ -40,6 +57,9 @@ interface IStakingData { /** * @dev Individual delegation data of a delegator in a pool. + * @param shares Shares owned by a delegator in the pool + * @param tokensLocked Tokens locked for undelegation + * @param tokensLockedUntil Epoch when locked tokens can be withdrawn */ struct Delegation { uint256 shares; // Shares owned by a delegator in the pool @@ -49,6 +69,10 @@ interface IStakingData { /** * @dev Rebates parameters. Used to avoid stack too deep errors in Staking initialize function. + * @param alphaNumerator Alpha parameter numerator for rebate calculation + * @param alphaDenominator Alpha parameter denominator for rebate calculation + * @param lambdaNumerator Lambda parameter numerator for rebate calculation + * @param lambdaDenominator Lambda parameter denominator for rebate calculation */ struct RebatesParameters { uint32 alphaNumerator; diff --git a/packages/interfaces/contracts/contracts/staking/IStakingExtension.sol b/packages/interfaces/contracts/contracts/staking/IStakingExtension.sol index 0a13ab744..72c107b0a 100644 --- a/packages/interfaces/contracts/contracts/staking/IStakingExtension.sol +++ b/packages/interfaces/contracts/contracts/staking/IStakingExtension.sol @@ -1,14 +1,18 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; pragma abicoder v2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events + 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 + * @author Edge & Node + * @notice 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 @@ -18,6 +22,12 @@ interface IStakingExtension is IStakingData { /** * @dev DelegationPool struct as returned by delegationPools(), since * the original DelegationPool in IStakingData.sol contains a nested mapping. + * @param __DEPRECATED_cooldownBlocks Deprecated field for cooldown blocks + * @param indexingRewardCut Indexing reward cut in PPM + * @param queryFeeCut Query fee cut in PPM + * @param updatedAtBlock Block when the pool was last updated + * @param tokens Total tokens as pool reserves + * @param shares Total shares minted in the pool */ struct DelegationPoolReturn { uint32 __DEPRECATED_cooldownBlocks; // solhint-disable-line var-name-mixedcase @@ -29,14 +39,23 @@ interface IStakingExtension is IStakingData { } /** - * @dev Emitted when `delegator` delegated `tokens` to the `indexer`, the delegator + * @notice Emitted when `delegator` delegated `tokens` to the `indexer`, the delegator * gets `shares` for the delegation pool proportionally to the tokens staked. + * @param indexer Address of the indexer receiving the delegation + * @param delegator Address of the delegator + * @param tokens Amount of tokens delegated + * @param shares Amount of shares issued to the delegator */ event StakeDelegated(address indexed indexer, address indexed delegator, uint256 tokens, uint256 shares); /** - * @dev Emitted when `delegator` undelegated `tokens` from `indexer`. + * @notice Emitted when `delegator` undelegated `tokens` from `indexer`. * Tokens get locked for withdrawal after a period of time. + * @param indexer Address of the indexer from which tokens are undelegated + * @param delegator Address of the delegator + * @param tokens Amount of tokens undelegated + * @param shares Amount of shares returned + * @param until Epoch until which tokens are locked */ event StakeDelegatedLocked( address indexed indexer, @@ -47,18 +66,28 @@ interface IStakingExtension is IStakingData { ); /** - * @dev Emitted when `delegator` withdrew delegated `tokens` from `indexer`. + * @notice Emitted when `delegator` withdrew delegated `tokens` from `indexer`. + * @param indexer Address of the indexer from which tokens are withdrawn + * @param delegator Address of the delegator + * @param tokens Amount of tokens withdrawn */ event StakeDelegatedWithdrawn(address indexed indexer, address indexed delegator, uint256 tokens); /** - * @dev Emitted when `indexer` was slashed for a total of `tokens` amount. + * @notice Emitted when `indexer` was slashed for a total of `tokens` amount. * Tracks `reward` amount of tokens given to `beneficiary`. + * @param indexer Address of the indexer that was slashed + * @param tokens Total amount of tokens slashed + * @param reward Amount of tokens given as reward + * @param beneficiary Address receiving the reward */ event StakeSlashed(address indexed indexer, uint256 tokens, uint256 reward, address beneficiary); /** - * @dev Emitted when `caller` set `slasher` address as `allowed` to slash stakes. + * @notice Emitted when `caller` set `slasher` address as `allowed` to slash stakes. + * @param caller Address that updated the slasher status + * @param slasher Address of the slasher + * @param allowed Whether the slasher is allowed to slash */ event SlasherUpdate(address indexed caller, address indexed slasher, bool allowed); @@ -67,16 +96,16 @@ interface IStakingExtension is IStakingData { * 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 + * @param newDelegationRatio Delegation capacity multiplier */ - function setDelegationRatio(uint32 delegationRatio) external; + function setDelegationRatio(uint32 newDelegationRatio) 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 + * @param newDelegationUnbondingPeriod Period in epochs to wait for token withdrawals after undelegating */ - function setDelegationUnbondingPeriod(uint32 delegationUnbondingPeriod) external; + function setDelegationUnbondingPeriod(uint32 newDelegationUnbondingPeriod) external; /** * @notice Set a delegation tax percentage to burn when delegated funds are deposited. @@ -114,6 +143,7 @@ interface IStakingExtension is IStakingData { * 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 + * @return Amount of tokens withdrawn */ function withdrawDelegated(address indexer, address newIndexer) external returns (uint256); diff --git a/packages/interfaces/contracts/contracts/staking/libs/IStakes.sol b/packages/interfaces/contracts/contracts/staking/libs/IStakes.sol index 701336409..3635a1263 100644 --- a/packages/interfaces/contracts/contracts/staking/libs/IStakes.sol +++ b/packages/interfaces/contracts/contracts/staking/libs/IStakes.sol @@ -1,8 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; pragma abicoder v2; +/** + * @title Interface for staking data structures + * @author Edge & Node + * @notice Defines the data structures used for indexer staking + */ interface IStakes { struct Indexer { uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer) diff --git a/packages/interfaces/contracts/contracts/token/IGraphToken.sol b/packages/interfaces/contracts/contracts/token/IGraphToken.sol index 8d5d1b845..5ad15d9f6 100644 --- a/packages/interfaces/contracts/contracts/token/IGraphToken.sol +++ b/packages/interfaces/contracts/contracts/token/IGraphToken.sol @@ -1,26 +1,68 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +// Solhint linting fails for 0.8.0. +// solhint-disable-next-line import-path-check import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +/** + * @title IGraphToken + * @author Edge & Node + * @notice Interface for the Graph Token contract + * @dev Extends IERC20 with additional functionality for minting, burning, and permit + */ interface IGraphToken is IERC20 { // -- Mint and Burn -- + /** + * @notice Burns tokens from the caller's account + * @param amount The amount of tokens to burn + */ function burn(uint256 amount) external; + /** + * @notice Burns tokens from a specified account (requires allowance) + * @param from The account to burn tokens from + * @param amount The amount of tokens to burn + */ function burnFrom(address from, uint256 amount) external; + /** + * @notice Mints new tokens to a specified account + * @dev Only callable by accounts with minter role + * @param to The account to mint tokens to + * @param amount The amount of tokens to mint + */ function mint(address to, uint256 amount) external; // -- Mint Admin -- + /** + * @notice Adds a new minter account + * @dev Only callable by accounts with appropriate permissions + * @param account The account to grant minter role to + */ function addMinter(address account) external; + /** + * @notice Removes minter role from an account + * @dev Only callable by accounts with appropriate permissions + * @param account The account to revoke minter role from + */ function removeMinter(address account) external; + /** + * @notice Renounces minter role for the caller + * @dev Allows a minter to voluntarily give up their minting privileges + */ function renounceMinter() external; + /** + * @notice Checks if an account has minter role + * @param account The account to check + * @return True if the account is a minter, false otherwise + */ function isMinter(address account) external view returns (bool); // -- Permit -- @@ -47,7 +89,19 @@ interface IGraphToken is IERC20 { // -- Allowance -- + /** + * @notice Increases the allowance granted to a spender + * @param spender The account whose allowance will be increased + * @param addedValue The amount to increase the allowance by + * @return True if the operation succeeded + */ function increaseAllowance(address spender, uint256 addedValue) external returns (bool); + /** + * @notice Decreases the allowance granted to a spender + * @param spender The account whose allowance will be decreased + * @param subtractedValue The amount to decrease the allowance by + * @return True if the operation succeeded + */ function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); } diff --git a/packages/interfaces/contracts/contracts/upgrades/IGraphProxy.sol b/packages/interfaces/contracts/contracts/upgrades/IGraphProxy.sol index 108708c03..641f41e4f 100644 --- a/packages/interfaces/contracts/contracts/upgrades/IGraphProxy.sol +++ b/packages/interfaces/contracts/contracts/upgrades/IGraphProxy.sol @@ -1,19 +1,77 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +/** + * @title Graph Proxy Interface + * @author Edge & Node + * @notice Interface for the Graph Proxy contract that handles upgradeable proxy functionality + */ interface IGraphProxy { + /** + * @notice Get the current admin. + * + * @dev NOTE: Only the admin can call this function. + * + * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the + * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. + * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` + * + * @return adminAddress The address of the current admin + */ function admin() external returns (address); + /** + * @notice Change the admin of the proxy. + * + * @dev NOTE: Only the admin can call this function. + * + * @param newAdmin Address of the new admin + */ function setAdmin(address newAdmin) external; + /** + * @notice Get the current implementation. + * + * @dev NOTE: Only the admin can call this function. + * + * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the + * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. + * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` + * + * @return implementationAddress The address of the current implementation for this proxy + */ function implementation() external returns (address); + /** + * @notice Get the current pending implementation. + * + * @dev NOTE: Only the admin can call this function. + * + * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the + * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. + * `0x9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c` + * + * @return pendingImplementationAddress The address of the current pending implementation for this proxy + */ function pendingImplementation() external returns (address); + /** + * @notice Upgrades to a new implementation contract. + * @dev NOTE: Only the admin can call this function. + * @param newImplementation Address of implementation contract + */ function upgradeTo(address newImplementation) external; + /** + * @notice Admin function for new implementation to accept its role as implementation. + */ function acceptUpgrade() external; + /** + * @notice Admin function for new implementation to accept its role as implementation, + * calling a function on the new implementation. + * @param data Calldata (including selector) for the function to delegatecall into the implementation + */ function acceptUpgradeAndCall(bytes calldata data) external; } diff --git a/packages/interfaces/contracts/contracts/upgrades/IGraphProxyAdmin.sol b/packages/interfaces/contracts/contracts/upgrades/IGraphProxyAdmin.sol index 44e0df0e4..7c6cfad6c 100644 --- a/packages/interfaces/contracts/contracts/upgrades/IGraphProxyAdmin.sol +++ b/packages/interfaces/contracts/contracts/upgrades/IGraphProxyAdmin.sol @@ -1,36 +1,87 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; import { IGraphProxy } from "./IGraphProxy.sol"; import { IGoverned } from "../governance/IGoverned.sol"; /** * @title IGraphProxyAdmin - * @dev GraphProxyAdmin contract interface + * @author Edge & Node + * @notice GraphProxyAdmin contract interface for managing proxy contracts * @dev Note that this interface is not used by the contract implementation, just used for types and abi generation * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ interface IGraphProxyAdmin is IGoverned { + /** + * @notice Get the implementation address of a proxy + * @param proxy The proxy contract to query + * @return The implementation address + */ function getProxyImplementation(IGraphProxy proxy) external view returns (address); + /** + * @notice Get the pending implementation address of a proxy + * @param proxy The proxy contract to query + * @return The pending implementation address + */ function getProxyPendingImplementation(IGraphProxy proxy) external view returns (address); + /** + * @notice Get the admin address of a proxy + * @param proxy The proxy contract to query + * @return The admin address + */ function getProxyAdmin(IGraphProxy proxy) external view returns (address); + /** + * @notice Change the admin of a proxy contract + * @param proxy The proxy contract to modify + * @param newAdmin The new admin address + */ function changeProxyAdmin(IGraphProxy proxy, address newAdmin) external; + /** + * @notice Upgrade a proxy to a new implementation + * @param proxy The proxy contract to upgrade + * @param implementation The new implementation address + */ function upgrade(IGraphProxy proxy, address implementation) external; + /** + * @notice Upgrade a proxy to a new implementation + * @param proxy The proxy contract to upgrade + * @param implementation The new implementation address + */ function upgradeTo(IGraphProxy proxy, address implementation) external; + /** + * @notice Upgrade a proxy to a new implementation and call a function + * @param proxy The proxy contract to upgrade + * @param implementation The new implementation address + * @param data The calldata to execute on the new implementation + */ function upgradeToAndCall(IGraphProxy proxy, address implementation, bytes calldata data) external; + /** + * @notice Accept ownership of a proxy contract + * @param proxy The proxy contract to accept + */ function acceptProxy(IGraphProxy proxy) external; + /** + * @notice Accept ownership of a proxy contract and call a function + * @param proxy The proxy contract to accept + * @param data The calldata to execute after accepting + */ function acceptProxyAndCall(IGraphProxy proxy, bytes calldata data) external; // storage + + /** + * @notice Get the governor address + * @return The address of the governor + */ function governor() external view returns (address); } diff --git a/packages/interfaces/contracts/data-service/IDataService.sol b/packages/interfaces/contracts/data-service/IDataService.sol index 778987f71..8fa18063b 100644 --- a/packages/interfaces/contracts/data-service/IDataService.sol +++ b/packages/interfaces/contracts/data-service/IDataService.sol @@ -1,10 +1,14 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events import { IGraphPayments } from "../horizon/IGraphPayments.sol"; /** * @title Interface of the base {DataService} contract as defined by the Graph Horizon specification. + * @author Edge & Node * @notice This interface provides a guardrail for contracts that use the Data Service framework * to implement a data service on Graph Horizon. Much of the specification is intentionally loose * to allow for greater flexibility when designing a data service. It's not possible to guarantee that diff --git a/packages/interfaces/contracts/data-service/IDataServiceFees.sol b/packages/interfaces/contracts/data-service/IDataServiceFees.sol index 9d235f4f7..9cba91d7a 100644 --- a/packages/interfaces/contracts/data-service/IDataServiceFees.sol +++ b/packages/interfaces/contracts/data-service/IDataServiceFees.sol @@ -1,10 +1,14 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events import { IDataService } from "./IDataService.sol"; /** * @title Interface for the {DataServiceFees} contract. + * @author Edge & Node * @notice Extension for the {IDataService} contract to handle payment collateralization * using a Horizon provision. * diff --git a/packages/interfaces/contracts/data-service/IDataServicePausable.sol b/packages/interfaces/contracts/data-service/IDataServicePausable.sol index 906e864a8..c95ba124a 100644 --- a/packages/interfaces/contracts/data-service/IDataServicePausable.sol +++ b/packages/interfaces/contracts/data-service/IDataServicePausable.sol @@ -1,10 +1,14 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events import { IDataService } from "./IDataService.sol"; /** * @title Interface for the {DataServicePausable} contract. + * @author Edge & Node * @notice Extension for the {IDataService} contract, adds pausing functionality * to the data service. Pausing is controlled by privileged accounts called * pause guardians. diff --git a/packages/interfaces/contracts/data-service/IDataServiceRescuable.sol b/packages/interfaces/contracts/data-service/IDataServiceRescuable.sol index f2cd7b06e..4607e664c 100644 --- a/packages/interfaces/contracts/data-service/IDataServiceRescuable.sol +++ b/packages/interfaces/contracts/data-service/IDataServiceRescuable.sol @@ -1,10 +1,14 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events import { IDataService } from "./IDataService.sol"; /** * @title Interface for the {IDataServicePausable} contract. + * @author Edge & Node * @notice Extension for the {IDataService} contract, adds the ability to rescue * any ERC20 token or ETH from the contract, controlled by a rescuer privileged role. * @custom:security-contact Please email security+contracts@thegraph.com if you find any diff --git a/packages/interfaces/contracts/horizon/IAuthorizable.sol b/packages/interfaces/contracts/horizon/IAuthorizable.sol index 7a7a77798..e83dee62b 100644 --- a/packages/interfaces/contracts/horizon/IAuthorizable.sol +++ b/packages/interfaces/contracts/horizon/IAuthorizable.sol @@ -1,8 +1,13 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events +// solhint-disable gas-struct-packing /** * @title Interface for the {Authorizable} contract + * @author Edge & Node * @notice Implements an authorization scheme that allows authorizers to * authorize signers to sign on their behalf. * @custom:security-contact Please email security+contracts@thegraph.com if you find any diff --git a/packages/interfaces/contracts/horizon/IGraphPayments.sol b/packages/interfaces/contracts/horizon/IGraphPayments.sol index 7a583f883..39955da88 100644 --- a/packages/interfaces/contracts/horizon/IGraphPayments.sol +++ b/packages/interfaces/contracts/horizon/IGraphPayments.sol @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; /** * @title Interface for the {GraphPayments} contract + * @author Edge & Node * @notice This contract is part of the Graph Horizon payments protocol. It's designed * to pull funds (GRT) from the {PaymentsEscrow} and distribute them according to a * set of pre established rules. diff --git a/packages/interfaces/contracts/horizon/IGraphTallyCollector.sol b/packages/interfaces/contracts/horizon/IGraphTallyCollector.sol index 86d0ebc3a..60b915cc4 100644 --- a/packages/interfaces/contracts/horizon/IGraphTallyCollector.sol +++ b/packages/interfaces/contracts/horizon/IGraphTallyCollector.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; import { IPaymentsCollector } from "./IPaymentsCollector.sol"; import { IGraphPayments } from "./IGraphPayments.sol"; @@ -7,6 +7,7 @@ import { IAuthorizable } from "./IAuthorizable.sol"; /** * @title Interface for the {GraphTallyCollector} contract + * @author Edge & Node * @dev Implements the {IPaymentCollector} interface as defined by the Graph * Horizon payments protocol. * @notice Implements a payments collector contract that can be used to collect @@ -49,8 +50,8 @@ interface IGraphTallyCollector is IPaymentsCollector, IAuthorizable { * @notice Emitted when a RAV is collected * @param collectionId The ID of the collection "bucket" the RAV belongs to. * @param payer The address of the payer - * @param dataService The address of the data service * @param serviceProvider The address of the service provider + * @param dataService The address of the data service * @param timestampNs The timestamp of the RAV * @param valueAggregate The total amount owed to the service provider * @param metadata Arbitrary metadata @@ -122,14 +123,14 @@ interface IGraphTallyCollector is IPaymentsCollector, IAuthorizable { ) external returns (uint256); /** - * @dev Recovers the signer address of a signed ReceiptAggregateVoucher (RAV). + * @notice Recovers the signer address of a signed ReceiptAggregateVoucher (RAV). * @param signedRAV The SignedRAV containing the RAV and its signature. * @return The address of the signer. */ function recoverRAVSigner(SignedRAV calldata signedRAV) external view returns (address); /** - * @dev Computes the hash of a ReceiptAggregateVoucher (RAV). + * @notice Computes the hash of a ReceiptAggregateVoucher (RAV). * @param rav The RAV for which to compute the hash. * @return The hash of the RAV. */ diff --git a/packages/interfaces/contracts/horizon/IHorizonStaking.sol b/packages/interfaces/contracts/horizon/IHorizonStaking.sol index 0ba4e26b3..4e680a1e5 100644 --- a/packages/interfaces/contracts/horizon/IHorizonStaking.sol +++ b/packages/interfaces/contracts/horizon/IHorizonStaking.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; import { IHorizonStakingTypes } from "./internal/IHorizonStakingTypes.sol"; import { IHorizonStakingMain } from "./internal/IHorizonStakingMain.sol"; @@ -9,6 +9,7 @@ import { IHorizonStakingExtension } from "./internal/IHorizonStakingExtension.so /** * @title Complete interface for the Horizon Staking contract + * @author Edge & Node * @notice This interface exposes all functions implemented by the {HorizonStaking} contract and its extension * {HorizonStakingExtension} as well as the custom data types used by the contract. * @dev Use this interface to interact with the Horizon Staking contract. diff --git a/packages/interfaces/contracts/horizon/IPaymentsCollector.sol b/packages/interfaces/contracts/horizon/IPaymentsCollector.sol index d37688462..a16aef951 100644 --- a/packages/interfaces/contracts/horizon/IPaymentsCollector.sol +++ b/packages/interfaces/contracts/horizon/IPaymentsCollector.sol @@ -1,11 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; import { IGraphPayments } from "./IGraphPayments.sol"; /** * @title Interface for a payments collector contract as defined by Graph Horizon payments protocol + * @author Edge & Node * @notice Contracts implementing this interface can be used with the payments protocol. First, a payer must * approve the collector to collect payments on their behalf. Only then can payment collection be initiated * using the collector contract. diff --git a/packages/interfaces/contracts/horizon/IPaymentsEscrow.sol b/packages/interfaces/contracts/horizon/IPaymentsEscrow.sol index 601783b12..9dbe9906a 100644 --- a/packages/interfaces/contracts/horizon/IPaymentsEscrow.sol +++ b/packages/interfaces/contracts/horizon/IPaymentsEscrow.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; import { IGraphPayments } from "./IGraphPayments.sol"; /** * @title Interface for the {PaymentsEscrow} contract + * @author Edge & Node * @notice This contract is part of the Graph Horizon payments protocol. It holds the funds (GRT) * for payments made through the payments protocol for services provided * via a Graph Horizon data service. diff --git a/packages/interfaces/contracts/horizon/internal/IHorizonStakingBase.sol b/packages/interfaces/contracts/horizon/internal/IHorizonStakingBase.sol index ba050ae3a..c48f20099 100644 --- a/packages/interfaces/contracts/horizon/internal/IHorizonStakingBase.sol +++ b/packages/interfaces/contracts/horizon/internal/IHorizonStakingBase.sol @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; import { IGraphPayments } from "../IGraphPayments.sol"; @@ -9,6 +12,7 @@ import { ILinkedList } from "./ILinkedList.sol"; /** * @title Interface for the {HorizonStakingBase} contract. + * @author Edge & Node * @notice Provides getters for {HorizonStaking} and {HorizonStakingExtension} storage variables. * @dev Most functions operate over {HorizonStaking} provisions. To uniquely identify a provision * functions take `serviceProvider` and `verifier` addresses. diff --git a/packages/interfaces/contracts/horizon/internal/IHorizonStakingExtension.sol b/packages/interfaces/contracts/horizon/internal/IHorizonStakingExtension.sol index d590a76a5..d487b2eca 100644 --- a/packages/interfaces/contracts/horizon/internal/IHorizonStakingExtension.sol +++ b/packages/interfaces/contracts/horizon/internal/IHorizonStakingExtension.sol @@ -1,11 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events import { IRewardsIssuer } from "../../contracts/rewards/IRewardsIssuer.sol"; /** * @title Interface for {HorizonStakingExtension} contract. + * @author Edge & Node * @notice Provides functions for managing legacy allocations. * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. @@ -50,7 +54,7 @@ interface IHorizonStakingExtension is IRewardsIssuer { } /** - * @dev Emitted when `indexer` close an allocation in `epoch` for `allocationID`. + * @notice 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. @@ -75,7 +79,7 @@ interface IHorizonStakingExtension is IRewardsIssuer { ); /** - * @dev Emitted when `indexer` collects a rebate on `subgraphDeploymentID` for `allocationID`. + * @notice 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. @@ -108,7 +112,7 @@ interface IHorizonStakingExtension is IRewardsIssuer { ); /** - * @dev Emitted when `indexer` was slashed for a total of `tokens` amount. + * @notice Emitted when `indexer` was slashed for a total of `tokens` amount. * Tracks `reward` amount of tokens given to `beneficiary`. * @param indexer The indexer address * @param tokens The amount of tokens slashed @@ -128,7 +132,7 @@ interface IHorizonStakingExtension is IRewardsIssuer { function closeAllocation(address allocationID, bytes32 poi) external; /** - * @dev Collect and rebate query fees to the indexer + * @notice Collect and rebate query fees to the indexer * This function will accept calls with zero tokens. * We use an exponential rebate formula to calculate the amount of tokens to rebate to the indexer. * This implementation allows collecting multiple times on the same allocation, keeping track of the diff --git a/packages/interfaces/contracts/horizon/internal/IHorizonStakingMain.sol b/packages/interfaces/contracts/horizon/internal/IHorizonStakingMain.sol index 1a84bcd67..19c1e1cf8 100644 --- a/packages/interfaces/contracts/horizon/internal/IHorizonStakingMain.sol +++ b/packages/interfaces/contracts/horizon/internal/IHorizonStakingMain.sol @@ -1,12 +1,16 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events import { IGraphPayments } from "../IGraphPayments.sol"; import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; /** * @title Inferface for the {HorizonStaking} contract. + * @author Edge & Node * @notice Provides functions for managing stake, provisions, delegations, and slashing. * @dev Note that this interface only includes the functions implemented by {HorizonStaking} contract, * and not those implemented by {HorizonStakingExtension}. @@ -110,7 +114,7 @@ interface IHorizonStakingMain { ); /** - * @dev Emitted when an operator is allowed or denied by a service provider for a particular verifier + * @notice Emitted when an operator is allowed or denied by a service provider for a particular verifier * @param serviceProvider The address of the service provider * @param verifier The address of the verifier * @param operator The address of the operator @@ -289,12 +293,12 @@ interface IHorizonStakingMain { /** * @notice Emitted when a series of thaw requests are fulfilled. + * @param requestType The type of thaw request * @param serviceProvider The address of the service provider * @param verifier The address of the verifier * @param owner The address of the owner of the thaw requests * @param thawRequestsFulfilled The number of thaw requests fulfilled * @param tokens The total amount of tokens being released - * @param requestType The type of thaw request */ event ThawRequestsFulfilled( IHorizonStakingTypes.ThawRequestType indexed requestType, diff --git a/packages/interfaces/contracts/horizon/internal/IHorizonStakingTypes.sol b/packages/interfaces/contracts/horizon/internal/IHorizonStakingTypes.sol index 0ab84fc1b..e8fff211b 100644 --- a/packages/interfaces/contracts/horizon/internal/IHorizonStakingTypes.sol +++ b/packages/interfaces/contracts/horizon/internal/IHorizonStakingTypes.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; /** * @title Defines the data types used in the Horizon staking contract + * @author Edge & Node + * @notice Interface defining data types and structures for Horizon staking * @dev In order to preserve storage compatibility some data structures keep deprecated fields. * These structures have then two representations, an internal one used by the contract storage and a public one. * Getter functions should retrieve internal representations, remove deprecated fields and return the public representation. diff --git a/packages/interfaces/contracts/horizon/internal/ILinkedList.sol b/packages/interfaces/contracts/horizon/internal/ILinkedList.sol index 4a993df29..4c099e65c 100644 --- a/packages/interfaces/contracts/horizon/internal/ILinkedList.sol +++ b/packages/interfaces/contracts/horizon/internal/ILinkedList.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; /** * @title Interface for the {LinkedList} library contract. + * @author Edge & Node + * @notice Interface for managing linked list data structures * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/interfaces/contracts/subgraph-service/IDisputeManager.sol b/packages/interfaces/contracts/subgraph-service/IDisputeManager.sol index e82c96fa9..da1324cc9 100644 --- a/packages/interfaces/contracts/subgraph-service/IDisputeManager.sol +++ b/packages/interfaces/contracts/subgraph-service/IDisputeManager.sol @@ -1,11 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events import { IAttestation } from "./internal/IAttestation.sol"; /** * @title IDisputeManager + * @author Edge & Node * @notice Interface for the {Dispute Manager} contract. * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. @@ -90,7 +94,7 @@ interface IDisputeManager { event SubgraphServiceSet(address indexed subgraphService); /** - * @dev Emitted when a query dispute is created for `subgraphDeploymentId` and `indexer` + * @notice Emitted when a query dispute is created for `subgraphDeploymentId` and `indexer` * by `fisherman`. * The event emits the amount of `tokens` deposited by the fisherman and `attestation` submitted. * @param disputeId The dispute id @@ -99,8 +103,8 @@ interface IDisputeManager { * @param tokens The amount of tokens deposited by the fisherman * @param subgraphDeploymentId The subgraph deployment id * @param attestation The attestation - * @param cancellableAt The timestamp when the dispute can be cancelled * @param stakeSnapshot The stake snapshot of the indexer at the time of the dispute + * @param cancellableAt The timestamp when the dispute can be cancelled */ event QueryDisputeCreated( bytes32 indexed disputeId, @@ -114,7 +118,7 @@ interface IDisputeManager { ); /** - * @dev Emitted when an indexing dispute is created for `allocationId` and `indexer` + * @notice Emitted when an indexing dispute is created for `allocationId` and `indexer` * by `fisherman`. * The event emits the amount of `tokens` deposited by the fisherman. * @param disputeId The dispute id @@ -140,7 +144,7 @@ interface IDisputeManager { ); /** - * @dev Emitted when a legacy dispute is created for `allocationId` and `fisherman`. + * @notice Emitted when a legacy dispute is created for `allocationId` and `fisherman`. * The event emits the amount of `tokensSlash` to slash and `tokensRewards` to reward the fisherman. * @param disputeId The dispute id * @param indexer The indexer address @@ -159,7 +163,7 @@ interface IDisputeManager { ); /** - * @dev Emitted when arbitrator accepts a `disputeId` to `indexer` created by `fisherman`. + * @notice Emitted when arbitrator accepts a `disputeId` to `indexer` created by `fisherman`. * The event emits the amount `tokens` transferred to the fisherman, the deposit plus reward. * @param disputeId The dispute id * @param indexer The indexer address @@ -174,7 +178,7 @@ interface IDisputeManager { ); /** - * @dev Emitted when arbitrator rejects a `disputeId` for `indexer` created by `fisherman`. + * @notice Emitted when arbitrator rejects a `disputeId` for `indexer` created by `fisherman`. * The event emits the amount `tokens` burned from the fisherman deposit. * @param disputeId The dispute id * @param indexer The indexer address @@ -189,7 +193,7 @@ interface IDisputeManager { ); /** - * @dev Emitted when arbitrator draw a `disputeId` for `indexer` created by `fisherman`. + * @notice Emitted when arbitrator draw a `disputeId` for `indexer` created by `fisherman`. * The event emits the amount `tokens` used as deposit and returned to the fisherman. * @param disputeId The dispute id * @param indexer The indexer address @@ -199,7 +203,7 @@ interface IDisputeManager { event DisputeDrawn(bytes32 indexed disputeId, address indexed indexer, address indexed fisherman, uint256 tokens); /** - * @dev Emitted when two disputes are in conflict to link them. + * @notice Emitted when two disputes are in conflict to link them. * This event will be emitted after each DisputeCreated event is emitted * for each of the individual disputes. * @param disputeId1 The first dispute id @@ -208,7 +212,7 @@ interface IDisputeManager { event DisputeLinked(bytes32 indexed disputeId1, bytes32 indexed disputeId2); /** - * @dev Emitted when a dispute is cancelled by the fisherman. + * @notice Emitted when a dispute is cancelled by the fisherman. * The event emits the amount `tokens` returned to the fisherman. * @param disputeId The dispute id * @param indexer The indexer address diff --git a/packages/interfaces/contracts/subgraph-service/ISubgraphService.sol b/packages/interfaces/contracts/subgraph-service/ISubgraphService.sol index 88e48d6d4..5b084c7a7 100644 --- a/packages/interfaces/contracts/subgraph-service/ISubgraphService.sol +++ b/packages/interfaces/contracts/subgraph-service/ISubgraphService.sol @@ -1,5 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events import { IDataServiceFees } from "../data-service/IDataServiceFees.sol"; import { IGraphPayments } from "../horizon/IGraphPayments.sol"; @@ -9,6 +12,7 @@ import { ILegacyAllocation } from "./internal/ILegacyAllocation.sol"; /** * @title Interface for the {SubgraphService} contract + * @author Edge & Node * @dev This interface extends {IDataServiceFees} and {IDataService}. * @notice The Subgraph Service is a data service built on top of Graph Horizon that supports the use case of * subgraph indexing and querying. The {SubgraphService} contract implements the flows described in the Data diff --git a/packages/interfaces/contracts/subgraph-service/internal/IAllocation.sol b/packages/interfaces/contracts/subgraph-service/internal/IAllocation.sol index 97b4f1176..a81e734d7 100644 --- a/packages/interfaces/contracts/subgraph-service/internal/IAllocation.sol +++ b/packages/interfaces/contracts/subgraph-service/internal/IAllocation.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; /** * @title Interface for the {Allocation} library contract. + * @author Edge & Node + * @notice Interface for managing allocation data and operations * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/interfaces/contracts/subgraph-service/internal/IAttestation.sol b/packages/interfaces/contracts/subgraph-service/internal/IAttestation.sol index e425a917a..fcee6d692 100644 --- a/packages/interfaces/contracts/subgraph-service/internal/IAttestation.sol +++ b/packages/interfaces/contracts/subgraph-service/internal/IAttestation.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; /** * @title Interface for the {Attestation} library contract. + * @author Edge & Node + * @notice Interface for managing attestation data and verification * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/interfaces/contracts/subgraph-service/internal/ILegacyAllocation.sol b/packages/interfaces/contracts/subgraph-service/internal/ILegacyAllocation.sol index 74405a439..c5bf7f8c7 100644 --- a/packages/interfaces/contracts/subgraph-service/internal/ILegacyAllocation.sol +++ b/packages/interfaces/contracts/subgraph-service/internal/ILegacyAllocation.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; /** * @title Interface for the {LegacyAllocation} library contract. + * @author Edge & Node + * @notice Interface for managing legacy allocation data * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/interfaces/contracts/token-distribution/IGraphTokenLockWallet.sol b/packages/interfaces/contracts/token-distribution/IGraphTokenLockWallet.sol index 735d35046..06e38dc20 100644 --- a/packages/interfaces/contracts/token-distribution/IGraphTokenLockWallet.sol +++ b/packages/interfaces/contracts/token-distribution/IGraphTokenLockWallet.sol @@ -1,8 +1,12 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events /** * @title IGraphTokenLockWallet + * @author Edge & Node * @notice Interface for the GraphTokenLockWallet contract that manages locked tokens with vesting schedules * @dev This interface includes core vesting functionality. Protocol interaction functions are in IGraphTokenLockWalletToolshed */ @@ -17,50 +21,157 @@ interface IGraphTokenLockWallet { } // Events + + /// @notice Emitted when the manager is updated + /// @param _oldManager The previous manager address + /// @param _newManager The new manager address event ManagerUpdated(address indexed _oldManager, address indexed _newManager); + + /// @notice Emitted when ownership is transferred + /// @param previousOwner The previous owner address + /// @param newOwner The new owner address event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /// @notice Emitted when token destinations are approved event TokenDestinationsApproved(); + + /// @notice Emitted when token destinations are revoked event TokenDestinationsRevoked(); + + /// @notice Emitted when tokens are released to beneficiary + /// @param beneficiary The beneficiary address + /// @param amount The amount of tokens released event TokensReleased(address indexed beneficiary, uint256 amount); + + /// @notice Emitted when tokens are revoked + /// @param beneficiary The beneficiary address + /// @param amount The amount of tokens revoked event TokensRevoked(address indexed beneficiary, uint256 amount); + + /// @notice Emitted when tokens are withdrawn + /// @param beneficiary The beneficiary address + /// @param amount The amount of tokens withdrawn event TokensWithdrawn(address indexed beneficiary, uint256 amount); // View functions - Vesting Details + + /// @notice Get the beneficiary address + /// @return The beneficiary address function beneficiary() external view returns (address); + + /// @notice Get the token contract address + /// @return The token contract address function token() external view returns (address); + + /// @notice Get the total amount of tokens managed by this contract + /// @return The managed token amount function managedAmount() external view returns (uint256); + + /// @notice Get the vesting start time + /// @return The start time timestamp function startTime() external view returns (uint256); + + /// @notice Get the vesting end time + /// @return The end time timestamp function endTime() external view returns (uint256); + + /// @notice Get the number of vesting periods + /// @return The number of periods function periods() external view returns (uint256); + + /// @notice Get the release start time + /// @return The release start time timestamp function releaseStartTime() external view returns (uint256); + + /// @notice Get the vesting cliff time + /// @return The cliff time timestamp function vestingCliffTime() external view returns (uint256); + + /// @notice Get the revocability status + /// @return The revocability status function revocable() external view returns (Revocability); + + /// @notice Check if the vesting has been revoked + /// @return True if revoked, false otherwise function isRevoked() external view returns (bool); // View functions - Vesting Calculations + + /// @notice Get the current timestamp + /// @return The current timestamp function currentTime() external view returns (uint256); + + /// @notice Get the total vesting duration + /// @return The duration in seconds function duration() external view returns (uint256); + + /// @notice Get the time elapsed since vesting start + /// @return The elapsed time in seconds function sinceStartTime() external view returns (uint256); + + /// @notice Get the amount of tokens released per period + /// @return The amount per period function amountPerPeriod() external view returns (uint256); + + /// @notice Get the duration of each vesting period + /// @return The period duration in seconds function periodDuration() external view returns (uint256); + + /// @notice Get the current vesting period + /// @return The current period number function currentPeriod() external view returns (uint256); + + /// @notice Get the number of periods that have passed + /// @return The number of passed periods function passedPeriods() external view returns (uint256); // View functions - Token Amounts + + /// @notice Get the amount of tokens that can be released + /// @return The releasable token amount function releasableAmount() external view returns (uint256); + + /// @notice Get the amount of tokens that have vested + /// @return The vested token amount function vestedAmount() external view returns (uint256); + + /// @notice Get the amount of tokens that have been released + /// @return The released token amount function releasedAmount() external view returns (uint256); + + /// @notice Get the amount of tokens that have been used + /// @return The used token amount function usedAmount() external view returns (uint256); + + /// @notice Get the current token balance of the contract + /// @return The current balance function currentBalance() external view returns (uint256); + + /// @notice Get the surplus amount of tokens + /// @return The surplus token amount function surplusAmount() external view returns (uint256); + + /// @notice Get the total outstanding token amount + /// @return The total outstanding amount function totalOutstandingAmount() external view returns (uint256); // State-changing functions + + /// @notice Release vested tokens to the beneficiary function release() external; + + /// @notice Withdraw surplus tokens + /// @param _amount The amount of surplus tokens to withdraw function withdrawSurplus(uint256 _amount) external; + + /// @notice Approve protocol interactions function approveProtocol() external; + + /// @notice Revoke protocol interactions function revokeProtocol() external; // Fallback for forwarding calls + + /// @notice Fallback function for forwarding calls fallback() external payable; } diff --git a/packages/interfaces/contracts/toolshed/IControllerToolshed.sol b/packages/interfaces/contracts/toolshed/IControllerToolshed.sol index e4dbd8d41..8b00216f7 100644 --- a/packages/interfaces/contracts/toolshed/IControllerToolshed.sol +++ b/packages/interfaces/contracts/toolshed/IControllerToolshed.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; + +// solhint-disable use-natspec import { IController } from "../contracts/governance/IController.sol"; import { IGoverned } from "../contracts/governance/IGoverned.sol"; diff --git a/packages/interfaces/contracts/toolshed/IDisputeManagerToolshed.sol b/packages/interfaces/contracts/toolshed/IDisputeManagerToolshed.sol index 0496d3326..8c3e4390e 100644 --- a/packages/interfaces/contracts/toolshed/IDisputeManagerToolshed.sol +++ b/packages/interfaces/contracts/toolshed/IDisputeManagerToolshed.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// solhint-disable use-natspec import { IDisputeManager } from "../subgraph-service/IDisputeManager.sol"; import { IOwnable } from "./internal/IOwnable.sol"; diff --git a/packages/interfaces/contracts/toolshed/IEpochManagerToolshed.sol b/packages/interfaces/contracts/toolshed/IEpochManagerToolshed.sol index 427df1f64..649ae7150 100644 --- a/packages/interfaces/contracts/toolshed/IEpochManagerToolshed.sol +++ b/packages/interfaces/contracts/toolshed/IEpochManagerToolshed.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; + +// solhint-disable use-natspec import { IEpochManager } from "../contracts/epochs/IEpochManager.sol"; diff --git a/packages/interfaces/contracts/toolshed/IGraphTallyCollectorToolshed.sol b/packages/interfaces/contracts/toolshed/IGraphTallyCollectorToolshed.sol index f6be272e4..100e83ff1 100644 --- a/packages/interfaces/contracts/toolshed/IGraphTallyCollectorToolshed.sol +++ b/packages/interfaces/contracts/toolshed/IGraphTallyCollectorToolshed.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// solhint-disable use-natspec import { IGraphTallyCollector } from "../horizon/IGraphTallyCollector.sol"; diff --git a/packages/interfaces/contracts/toolshed/IGraphTokenLockWalletToolshed.sol b/packages/interfaces/contracts/toolshed/IGraphTokenLockWalletToolshed.sol index d442f0c0f..b412f6eb7 100644 --- a/packages/interfaces/contracts/toolshed/IGraphTokenLockWalletToolshed.sol +++ b/packages/interfaces/contracts/toolshed/IGraphTokenLockWalletToolshed.sol @@ -1,11 +1,14 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; + +// solhint-disable use-natspec import { IGraphTokenLockWallet } from "../token-distribution/IGraphTokenLockWallet.sol"; import { IGraphPayments } from "../horizon/IGraphPayments.sol"; /** * @title IGraphTokenLockWalletToolshed + * @author Edge & Node * @notice Extended interface for GraphTokenLockWallet that includes Horizon protocol interaction functions * @dev Functions included are based on the GraphTokenLockManager whitelist for vesting contracts on Horizon */ diff --git a/packages/interfaces/contracts/toolshed/IHorizonStakingToolshed.sol b/packages/interfaces/contracts/toolshed/IHorizonStakingToolshed.sol index b021d3af9..59e549998 100644 --- a/packages/interfaces/contracts/toolshed/IHorizonStakingToolshed.sol +++ b/packages/interfaces/contracts/toolshed/IHorizonStakingToolshed.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; + +// solhint-disable use-natspec import { IHorizonStaking } from "../horizon/IHorizonStaking.sol"; import { IMulticall } from "../contracts/base/IMulticall.sol"; diff --git a/packages/interfaces/contracts/toolshed/IL2CurationToolshed.sol b/packages/interfaces/contracts/toolshed/IL2CurationToolshed.sol index 9b4b81782..aae712596 100644 --- a/packages/interfaces/contracts/toolshed/IL2CurationToolshed.sol +++ b/packages/interfaces/contracts/toolshed/IL2CurationToolshed.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; + +// solhint-disable use-natspec import { ICuration } from "../contracts/curation/ICuration.sol"; import { IL2Curation } from "../contracts/l2/curation/IL2Curation.sol"; diff --git a/packages/interfaces/contracts/toolshed/IL2GNSToolshed.sol b/packages/interfaces/contracts/toolshed/IL2GNSToolshed.sol index 7cfb3a579..c672be2c8 100644 --- a/packages/interfaces/contracts/toolshed/IL2GNSToolshed.sol +++ b/packages/interfaces/contracts/toolshed/IL2GNSToolshed.sol @@ -1,5 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; +pragma abicoder v2; + +// solhint-disable use-natspec import { IGNS } from "../contracts/discovery/IGNS.sol"; import { IL2GNS } from "../contracts/l2/discovery/IL2GNS.sol"; diff --git a/packages/interfaces/contracts/toolshed/IPaymentsEscrowToolshed.sol b/packages/interfaces/contracts/toolshed/IPaymentsEscrowToolshed.sol index e77a0a1b0..c7b9b81f2 100644 --- a/packages/interfaces/contracts/toolshed/IPaymentsEscrowToolshed.sol +++ b/packages/interfaces/contracts/toolshed/IPaymentsEscrowToolshed.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// solhint-disable use-natspec import { IPaymentsEscrow } from "../horizon/IPaymentsEscrow.sol"; diff --git a/packages/interfaces/contracts/toolshed/IRewardsManagerToolshed.sol b/packages/interfaces/contracts/toolshed/IRewardsManagerToolshed.sol index 9fd0b6e1b..03b584ba4 100644 --- a/packages/interfaces/contracts/toolshed/IRewardsManagerToolshed.sol +++ b/packages/interfaces/contracts/toolshed/IRewardsManagerToolshed.sol @@ -1,5 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; + +// solhint-disable use-natspec + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events import { IRewardsManager } from "../contracts/rewards/IRewardsManager.sol"; @@ -10,23 +15,23 @@ interface IRewardsManagerToolshed is IRewardsManager { event RewardsAssigned(address indexed indexer, address indexed allocationID, uint256 amount); /** - * @dev Emitted when rewards are assigned to an indexer. + * @notice Emitted when rewards are assigned to an indexer (Horizon version) * @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. + * @notice Emitted when rewards are denied to an indexer */ event RewardsDenied(address indexed indexer, address indexed allocationID); /** - * @dev Emitted when a subgraph is denied for claiming rewards. + * @notice Emitted when a subgraph is denied for claiming rewards */ event RewardsDenylistUpdated(bytes32 indexed subgraphDeploymentID, uint256 sinceBlock); /** - * @dev Emitted when the subgraph service is set + * @notice Emitted when the subgraph service is set */ event SubgraphServiceSet(address indexed oldSubgraphService, address indexed newSubgraphService); diff --git a/packages/interfaces/contracts/toolshed/IServiceRegistryToolshed.sol b/packages/interfaces/contracts/toolshed/IServiceRegistryToolshed.sol index 59155f1f7..46b644418 100644 --- a/packages/interfaces/contracts/toolshed/IServiceRegistryToolshed.sol +++ b/packages/interfaces/contracts/toolshed/IServiceRegistryToolshed.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.27; +pragma solidity ^0.7.6 || ^0.8.0; + +// solhint-disable use-natspec import { IServiceRegistry } from "../contracts/discovery/IServiceRegistry.sol"; diff --git a/packages/interfaces/contracts/toolshed/ISubgraphServiceToolshed.sol b/packages/interfaces/contracts/toolshed/ISubgraphServiceToolshed.sol index 6d684c7ba..a7a05fbcd 100644 --- a/packages/interfaces/contracts/toolshed/ISubgraphServiceToolshed.sol +++ b/packages/interfaces/contracts/toolshed/ISubgraphServiceToolshed.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// solhint-disable use-natspec import { ISubgraphService } from "../subgraph-service/ISubgraphService.sol"; import { IOwnable } from "./internal/IOwnable.sol"; diff --git a/packages/interfaces/contracts/toolshed/internal/IAllocationManager.sol b/packages/interfaces/contracts/toolshed/internal/IAllocationManager.sol index d00b9a9f4..9e6e8b704 100644 --- a/packages/interfaces/contracts/toolshed/internal/IAllocationManager.sol +++ b/packages/interfaces/contracts/toolshed/internal/IAllocationManager.sol @@ -1,5 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// solhint-disable use-natspec + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events interface IAllocationManager { // Events diff --git a/packages/interfaces/contracts/toolshed/internal/IOwnable.sol b/packages/interfaces/contracts/toolshed/internal/IOwnable.sol index d5b894c58..00628a696 100644 --- a/packages/interfaces/contracts/toolshed/internal/IOwnable.sol +++ b/packages/interfaces/contracts/toolshed/internal/IOwnable.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.27; +// solhint-disable use-natspec + +pragma solidity ^0.8.22; /// @title IOwnable /// @notice Interface for Ownable contracts diff --git a/packages/interfaces/contracts/toolshed/internal/IPausable.sol b/packages/interfaces/contracts/toolshed/internal/IPausable.sol index aee534ce3..456dfb534 100644 --- a/packages/interfaces/contracts/toolshed/internal/IPausable.sol +++ b/packages/interfaces/contracts/toolshed/internal/IPausable.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// solhint-disable use-natspec /// @title IPausable /// @notice Interface for Pausable contract diff --git a/packages/interfaces/contracts/toolshed/internal/IProvisionManager.sol b/packages/interfaces/contracts/toolshed/internal/IProvisionManager.sol index 4a536e5e1..26cafdc31 100644 --- a/packages/interfaces/contracts/toolshed/internal/IProvisionManager.sol +++ b/packages/interfaces/contracts/toolshed/internal/IProvisionManager.sol @@ -1,5 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +pragma solidity ^0.8.22; + +// solhint-disable use-natspec + +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events interface IProvisionManager { // Events diff --git a/packages/interfaces/contracts/toolshed/internal/IProvisionTracker.sol b/packages/interfaces/contracts/toolshed/internal/IProvisionTracker.sol index f474be14e..b0a1108a3 100644 --- a/packages/interfaces/contracts/toolshed/internal/IProvisionTracker.sol +++ b/packages/interfaces/contracts/toolshed/internal/IProvisionTracker.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.27; +// solhint-disable use-natspec + +pragma solidity ^0.8.22; interface IProvisionTracker { // Errors diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 390efb8ce..6f73b2c5d 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -1,7 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.27; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable function-max-lines, gas-strict-inequalities + +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStaking } from "@graphprotocol/interfaces/contracts/horizon/IHorizonStaking.sol"; import { IDisputeManager } from "@graphprotocol/interfaces/contracts/subgraph-service/IDisputeManager.sol"; import { ISubgraphService } from "@graphprotocol/interfaces/contracts/subgraph-service/ISubgraphService.sol"; @@ -21,7 +24,8 @@ import { AttestationManager } from "./utilities/AttestationManager.sol"; /** * @title DisputeManager - * @notice Provides a way to permissionlessly create disputes for incorrect behavior in the Subgraph Service. + * @author Edge & Node + * @notice Provides a way to permissionlessly create disputes for incorrect behavior in the Subgraph Service * * There are two types of disputes that can be created: Query disputes and Indexing disputes. * diff --git a/packages/subgraph-service/contracts/DisputeManagerStorage.sol b/packages/subgraph-service/contracts/DisputeManagerStorage.sol index 7441efd00..38b6e3115 100644 --- a/packages/subgraph-service/contracts/DisputeManagerStorage.sol +++ b/packages/subgraph-service/contracts/DisputeManagerStorage.sol @@ -7,7 +7,8 @@ import { ISubgraphService } from "@graphprotocol/interfaces/contracts/subgraph-s /** * @title DisputeManagerStorage - * @notice This contract holds all the storage variables for the Dispute Manager contract. + * @author Edge & Node + * @notice This contract holds all the storage variables for the Dispute Manager contract * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index aeb4eb827..0ba0b3035 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -1,8 +1,12 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities +// solhint-disable function-max-lines + import { IGraphPayments } from "@graphprotocol/interfaces/contracts/horizon/IGraphPayments.sol"; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { IGraphTallyCollector } from "@graphprotocol/interfaces/contracts/horizon/IGraphTallyCollector.sol"; import { IRewardsIssuer } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsIssuer.sol"; import { IDataService } from "@graphprotocol/interfaces/contracts/data-service/IDataService.sol"; @@ -26,6 +30,8 @@ import { Allocation } from "./libraries/Allocation.sol"; /** * @title SubgraphService contract + * @author Edge & Node + * @notice A data service contract for subgraph indexing and querying * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol index 133963347..04dc4abf9 100644 --- a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol +++ b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol @@ -5,7 +5,8 @@ import { ISubgraphService } from "@graphprotocol/interfaces/contracts/subgraph-s /** * @title SubgraphServiceStorage - * @notice This contract holds all the storage variables for the Subgraph Service contract. + * @author Edge & Node + * @notice This contract holds all the storage variables for the Subgraph Service contract * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index 88f7195b8..5a4e3cb52 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -7,7 +7,8 @@ import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; /** * @title Allocation library - * @notice A library to handle Allocations. + * @author Edge & Node + * @notice A library to handle Allocations * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/subgraph-service/contracts/libraries/Attestation.sol b/packages/subgraph-service/contracts/libraries/Attestation.sol index d821fbfbc..25bb6651f 100644 --- a/packages/subgraph-service/contracts/libraries/Attestation.sol +++ b/packages/subgraph-service/contracts/libraries/Attestation.sol @@ -1,11 +1,15 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities + import { IAttestation } from "@graphprotocol/interfaces/contracts/subgraph-service/internal/IAttestation.sol"; /** * @title Attestation library - * @notice A library to handle Attestation. + * @author Edge & Node + * @notice A library to handle Attestation * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ @@ -44,8 +48,8 @@ library Attestation { uint256 private constant BYTES32_BYTE_LENGTH = 32; /** - * @dev Returns if two attestations are conflicting. - * Everything must match except for the responseId. + * @notice Returns if two attestations are conflicting + * @dev Everything must match except for the responseId * @param _attestation1 Attestation * @param _attestation2 Attestation * @return True if the two attestations are conflicting @@ -60,7 +64,7 @@ library Attestation { } /** - * @dev Parse the bytes attestation into a struct from `_data`. + * @notice Parse the bytes attestation into a struct from `_data` * @param _data The bytes to parse * @return Attestation struct */ @@ -87,7 +91,7 @@ library Attestation { } /** - * @dev Parse a uint8 from `_bytes` starting at offset `_start`. + * @notice Parse a uint8 from `_bytes` starting at offset `_start` * @param _bytes The bytes to parse * @param _start The start offset * @return uint8 value @@ -111,7 +115,7 @@ library Attestation { } /** - * @dev Parse a bytes32 from `_bytes` starting at offset `_start`. + * @notice Parse a bytes32 from `_bytes` starting at offset `_start` * @param _bytes The bytes to parse * @param _start The start offset * @return bytes32 value diff --git a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol index 2d73abd91..4717cefed 100644 --- a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol +++ b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol @@ -6,7 +6,8 @@ import { ILegacyAllocation } from "@graphprotocol/interfaces/contracts/subgraph- /** * @title LegacyAllocation library - * @notice A library to handle legacy Allocations. + * @author Edge & Node + * @notice A library to handle legacy Allocations * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index e095b3282..08608d8b4 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -1,8 +1,13 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events +// solhint-disable gas-small-strings +// solhint-disable function-max-lines + import { IGraphPayments } from "@graphprotocol/interfaces/contracts/horizon/IGraphPayments.sol"; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/interfaces/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStakingTypes } from "@graphprotocol/interfaces/contracts/horizon/internal/IHorizonStakingTypes.sol"; import { IAllocation } from "@graphprotocol/interfaces/contracts/subgraph-service/internal/IAllocation.sol"; import { ILegacyAllocation } from "@graphprotocol/interfaces/contracts/subgraph-service/internal/ILegacyAllocation.sol"; @@ -20,7 +25,8 @@ import { ProvisionTracker } from "@graphprotocol/horizon/contracts/data-service/ /** * @title AllocationManager contract - * @notice A helper contract implementing allocation lifecycle management. + * @author Edge & Node + * @notice A helper contract implementing allocation lifecycle management * Allows opening, resizing, and closing allocations, as well as collecting indexing rewards by presenting a Proof * of Indexing (POI). * @custom:security-contact Please email security+contracts@thegraph.com if you find any @@ -63,8 +69,8 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca * @param tokensIndexerRewards The amount of tokens collected for the indexer * @param tokensDelegationRewards The amount of tokens collected for delegators * @param poi The POI presented - * @param currentEpoch The current epoch * @param poiMetadata The metadata associated with the POI + * @param currentEpoch The current epoch */ event IndexingRewardsCollected( address indexed indexer, @@ -95,7 +101,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca ); /** - * @dev Emitted when an indexer closes an allocation + * @notice Emitted when an indexer closes an allocation * @param indexer The address of the indexer * @param allocationId The id of the allocation * @param subgraphDeploymentId The id of the subgraph deployment diff --git a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol index 4c0870291..a56e649fd 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol @@ -6,7 +6,8 @@ import { ILegacyAllocation } from "@graphprotocol/interfaces/contracts/subgraph- /** * @title AllocationManagerStorage - * @notice This contract holds all the storage variables for the Allocation Manager contract. + * @author Edge & Node + * @notice This contract holds all the storage variables for the Allocation Manager contract * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/subgraph-service/contracts/utilities/AttestationManager.sol b/packages/subgraph-service/contracts/utilities/AttestationManager.sol index f385beeb5..2c45fad3a 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManager.sol @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-small-strings + import { IAttestation } from "@graphprotocol/interfaces/contracts/subgraph-service/internal/IAttestation.sol"; import { AttestationManagerV1Storage } from "./AttestationManagerStorage.sol"; @@ -10,7 +13,8 @@ import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/I /** * @title AttestationManager contract - * @notice A helper contract implementing attestation verification. + * @author Edge & Node + * @notice A helper contract implementing attestation verification * Uses a custom implementation of EIP712 for backwards compatibility with attestations. * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. @@ -34,18 +38,18 @@ abstract contract AttestationManager is Initializable, AttestationManagerV1Stora bytes32 private constant DOMAIN_SALT = 0xa070ffb1cd7409649bf77822cce74495468e06dbfaef09556838bf188679b9c2; /** - * @dev Initialize the AttestationManager contract and parent contracts + * @notice Initialize the AttestationManager contract and parent contracts */ - // solhint-disable-next-line func-name-mixedcase function __AttestationManager_init() internal onlyInitializing { + // solhint-disable-previous-line func-name-mixedcase __AttestationManager_init_unchained(); } /** - * @dev Initialize the AttestationManager contract + * @notice Initialize the AttestationManager contract */ - // solhint-disable-next-line func-name-mixedcase function __AttestationManager_init_unchained() internal onlyInitializing { + // solhint-disable-previous-line func-name-mixedcase _domainSeparator = keccak256( abi.encode( DOMAIN_TYPE_HASH, @@ -59,7 +63,7 @@ abstract contract AttestationManager is Initializable, AttestationManagerV1Stora } /** - * @dev Recover the signer address of the `_attestation`. + * @notice Recover the signer address of the `_attestation` * @param _attestation The attestation struct * @return Signer address */ diff --git a/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol index 1c720ec8c..1559a52fa 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol @@ -3,7 +3,8 @@ pragma solidity 0.8.27; /** * @title AttestationManagerStorage - * @notice This contract holds all the storage variables for the Attestation Manager contract. + * @author Edge & Node + * @notice This contract holds all the storage variables for the Attestation Manager contract * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ diff --git a/packages/subgraph-service/contracts/utilities/Directory.sol b/packages/subgraph-service/contracts/utilities/Directory.sol index 6b96616f4..4bfc1daa0 100644 --- a/packages/subgraph-service/contracts/utilities/Directory.sol +++ b/packages/subgraph-service/contracts/utilities/Directory.sol @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.27; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events + import { IDisputeManager } from "@graphprotocol/interfaces/contracts/subgraph-service/IDisputeManager.sol"; import { ISubgraphService } from "@graphprotocol/interfaces/contracts/subgraph-service/ISubgraphService.sol"; import { IGraphTallyCollector } from "@graphprotocol/interfaces/contracts/horizon/IGraphTallyCollector.sol"; @@ -8,7 +11,8 @@ import { ICuration } from "@graphprotocol/interfaces/contracts/contracts/curatio /** * @title Directory contract - * @notice This contract is meant to be inherited by {SubgraphService} contract. + * @author Edge & Node + * @notice This contract is meant to be inherited by {SubgraphService} contract * It contains the addresses of the contracts that the contract interacts with. * Uses immutable variables to minimize gas costs. * @custom:security-contact Please email security+contracts@thegraph.com if you find any diff --git a/packages/subgraph-service/test/unit/mocks/MockRewardsManager.sol b/packages/subgraph-service/test/unit/mocks/MockRewardsManager.sol index b3724daae..8286f2570 100644 --- a/packages/subgraph-service/test/unit/mocks/MockRewardsManager.sol +++ b/packages/subgraph-service/test/unit/mocks/MockRewardsManager.sol @@ -71,6 +71,12 @@ contract MockRewardsManager is IRewardsManager { function calcRewards(uint256, uint256) external pure returns (uint256) {} + function getRewardsIssuancePerBlock() external view returns (uint256) {} + + // -- Setters -- + + function setRewardsEligibilityOracle(address newRewardsEligibilityOracle) external {} + // -- Updates -- function updateAccRewardsPerSignal() external returns (uint256) {} diff --git a/packages/token-distribution/contracts/GraphTokenDistributor.sol b/packages/token-distribution/contracts/GraphTokenDistributor.sol index a7cd88137..79c2dd399 100644 --- a/packages/token-distribution/contracts/GraphTokenDistributor.sol +++ b/packages/token-distribution/contracts/GraphTokenDistributor.sol @@ -2,10 +2,14 @@ pragma solidity ^0.7.3; -import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/math/SafeMath.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec, gas-indexed-events, gas-increment-by-one +// solhint-disable named-parameters-mapping + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; /** * @title GraphTokenDistributor diff --git a/packages/token-distribution/contracts/GraphTokenLock.sol b/packages/token-distribution/contracts/GraphTokenLock.sol index 03cfbca43..545b25413 100644 --- a/packages/token-distribution/contracts/GraphTokenLock.sol +++ b/packages/token-distribution/contracts/GraphTokenLock.sol @@ -2,13 +2,16 @@ pragma solidity ^0.7.3; -import "@openzeppelin/contracts/math/SafeMath.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec, gas-indexed-events, gas-strict-inequalities, gas-small-strings + +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import { Ownable as OwnableInitializable } from "./Ownable.sol"; -import "./MathUtils.sol"; -import "./IGraphTokenLock.sol"; +import { MathUtils } from "./MathUtils.sol"; +import { IGraphTokenLock } from "./IGraphTokenLock.sol"; /** * @title GraphTokenLock @@ -54,7 +57,7 @@ abstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock { // A cliff set a date to which a beneficiary needs to get to vest // all preceding periods uint256 public vestingCliffTime; - Revocability public revocable; // Whether to use vesting for locked funds + IGraphTokenLock.Revocability public revocable; // Whether to use vesting for locked funds // State @@ -103,7 +106,7 @@ abstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock { uint256 _periods, uint256 _releaseStartTime, uint256 _vestingCliffTime, - Revocability _revocable + IGraphTokenLock.Revocability _revocable ) internal { require(!isInitialized, "Already initialized"); require(_owner != address(0), "Owner cannot be zero"); @@ -113,7 +116,7 @@ abstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock { require(_startTime != 0, "Start time must be set"); require(_startTime < _endTime, "Start time > end time"); require(_periods >= MIN_PERIOD, "Periods cannot be below minimum"); - require(_revocable != Revocability.NotSet, "Must set a revocability option"); + require(_revocable != IGraphTokenLock.Revocability.NotSet, "Must set a revocability option"); require(_releaseStartTime < _endTime, "Release start time must be before end time"); require(_vestingCliffTime < _endTime, "Cliff time must be before end time"); @@ -271,7 +274,7 @@ abstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock { */ function vestedAmount() public view override returns (uint256) { // If non-revocable it is fully vested - if (revocable == Revocability.Disabled) { + if (revocable == IGraphTokenLock.Revocability.Disabled) { return managedAmount; } @@ -298,7 +301,11 @@ abstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock { // Vesting cliff is activated and it has not passed means nothing is vested yet // so funds cannot be released - if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) { + if ( + revocable == IGraphTokenLock.Revocability.Enabled && + vestingCliffTime > 0 && + currentTime() < vestingCliffTime + ) { return 0; } @@ -368,7 +375,7 @@ abstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock { * @dev Vesting schedule is always calculated based on managed tokens */ function revoke() external override onlyOwner { - require(revocable == Revocability.Enabled, "Contract is non-revocable"); + require(revocable == IGraphTokenLock.Revocability.Enabled, "Contract is non-revocable"); require(isRevoked == false, "Already revoked"); uint256 unvestedAmount = managedAmount.sub(vestedAmount()); diff --git a/packages/token-distribution/contracts/GraphTokenLockManager.sol b/packages/token-distribution/contracts/GraphTokenLockManager.sol index 2ec96887e..8eb719685 100644 --- a/packages/token-distribution/contracts/GraphTokenLockManager.sol +++ b/packages/token-distribution/contracts/GraphTokenLockManager.sol @@ -3,14 +3,19 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; -import "@openzeppelin/contracts/utils/EnumerableSet.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec, gas-indexed-events, gas-strict-inequalities, gas-increment-by-one +// solhint-disable named-parameters-mapping + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; +import { Address } from "@openzeppelin/contracts/utils/Address.sol"; +import { EnumerableSet } from "@openzeppelin/contracts/utils/EnumerableSet.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import "./MinimalProxyFactory.sol"; -import "./IGraphTokenLockManager.sol"; +import { MinimalProxyFactory } from "./MinimalProxyFactory.sol"; +import { IGraphTokenLockManager } from "./IGraphTokenLockManager.sol"; +import { IGraphTokenLock } from "./IGraphTokenLock.sol"; import { GraphTokenLockWallet } from "./GraphTokenLockWallet.sol"; /** diff --git a/packages/token-distribution/contracts/GraphTokenLockSimple.sol b/packages/token-distribution/contracts/GraphTokenLockSimple.sol index e5b00a3fa..9f0ae48a9 100644 --- a/packages/token-distribution/contracts/GraphTokenLockSimple.sol +++ b/packages/token-distribution/contracts/GraphTokenLockSimple.sol @@ -2,7 +2,12 @@ pragma solidity ^0.7.3; -import "./GraphTokenLock.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + +import { GraphTokenLock } from "./GraphTokenLock.sol"; +import { IGraphTokenLock } from "./IGraphTokenLock.sol"; +import { Ownable as OwnableInitializable } from "./Ownable.sol"; /** * @title GraphTokenLockSimple @@ -29,7 +34,7 @@ contract GraphTokenLockSimple is GraphTokenLock { uint256 _periods, uint256 _releaseStartTime, uint256 _vestingCliffTime, - Revocability _revocable + IGraphTokenLock.Revocability _revocable ) external onlyOwner { _initialize( _owner, diff --git a/packages/token-distribution/contracts/GraphTokenLockWallet.sol b/packages/token-distribution/contracts/GraphTokenLockWallet.sol index 3ac24cb13..cbfaab372 100644 --- a/packages/token-distribution/contracts/GraphTokenLockWallet.sol +++ b/packages/token-distribution/contracts/GraphTokenLockWallet.sol @@ -3,12 +3,15 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; -import "@openzeppelin/contracts/utils/Address.sol"; -import "@openzeppelin/contracts/math/SafeMath.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec, gas-increment-by-one, gas-strict-inequalities, gas-small-strings -import "./GraphTokenLock.sol"; -import "./IGraphTokenLockManager.sol"; +import { Address } from "@openzeppelin/contracts/utils/Address.sol"; +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; + +import { GraphTokenLock, MathUtils } from "./GraphTokenLock.sol"; +import { IGraphTokenLock } from "./IGraphTokenLock.sol"; +import { IGraphTokenLockManager } from "./IGraphTokenLockManager.sol"; /** * @title GraphTokenLockWallet @@ -55,7 +58,7 @@ contract GraphTokenLockWallet is GraphTokenLock { uint256 _periods, uint256 _releaseStartTime, uint256 _vestingCliffTime, - Revocability _revocable + IGraphTokenLock.Revocability _revocable ) external { _initialize( _owner, @@ -130,7 +133,7 @@ contract GraphTokenLockWallet is GraphTokenLock { * @return Amount of tokens ready to be released */ function releasableAmount() public view override returns (uint256) { - if (revocable == Revocability.Disabled) { + if (revocable == IGraphTokenLock.Revocability.Disabled) { return super.releasableAmount(); } @@ -146,7 +149,11 @@ contract GraphTokenLockWallet is GraphTokenLock { // Vesting cliff is activated and it has not passed means nothing is vested yet // so funds cannot be released - if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) { + if ( + revocable == IGraphTokenLock.Revocability.Enabled && + vestingCliffTime > 0 && + currentTime() < vestingCliffTime + ) { return 0; } @@ -179,7 +186,7 @@ contract GraphTokenLockWallet is GraphTokenLock { // Tracked used tokens in the protocol // We do this check after balances were updated by the forwarded call // Check is only enforced for revocable contracts to save some gas - if (revocable == Revocability.Enabled) { + if (revocable == IGraphTokenLock.Revocability.Enabled) { // Track contract balance change uint256 newBalance = currentBalance(); if (newBalance < oldBalance) { diff --git a/packages/token-distribution/contracts/ICallhookReceiver.sol b/packages/token-distribution/contracts/ICallhookReceiver.sol deleted file mode 100644 index f8f01d56f..000000000 --- a/packages/token-distribution/contracts/ICallhookReceiver.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -// Copied from graphprotocol/contracts, changed solidity version to 0.7.3 - -/** - * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge - * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must - * be allowlisted by the governor, but also implement this interface that contains - * the function that will actually be called by the L2GraphTokenGateway. - */ -pragma solidity ^0.7.3; - -interface ICallhookReceiver { - /** - * @notice Receive tokens with a callhook from the bridge - * @param _from Token sender in L1 - * @param _amount Amount of tokens that were transferred - * @param _data ABI-encoded callhook data - */ - function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external; -} diff --git a/packages/token-distribution/contracts/IGraphTokenLock.sol b/packages/token-distribution/contracts/IGraphTokenLock.sol index eac89f414..ccdaa004f 100644 --- a/packages/token-distribution/contracts/IGraphTokenLock.sol +++ b/packages/token-distribution/contracts/IGraphTokenLock.sol @@ -3,7 +3,8 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec interface IGraphTokenLock { enum Revocability { diff --git a/packages/token-distribution/contracts/IGraphTokenLockManager.sol b/packages/token-distribution/contracts/IGraphTokenLockManager.sol index c646e5e16..0897f4869 100644 --- a/packages/token-distribution/contracts/IGraphTokenLockManager.sol +++ b/packages/token-distribution/contracts/IGraphTokenLockManager.sol @@ -3,9 +3,12 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec -import "./IGraphTokenLock.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import { IGraphTokenLock } from "./IGraphTokenLock.sol"; interface IGraphTokenLockManager { // -- Factory -- diff --git a/packages/token-distribution/contracts/L1GraphTokenLockTransferTool.sol b/packages/token-distribution/contracts/L1GraphTokenLockTransferTool.sol index 962cf54ee..c6d7ffda8 100644 --- a/packages/token-distribution/contracts/L1GraphTokenLockTransferTool.sol +++ b/packages/token-distribution/contracts/L1GraphTokenLockTransferTool.sol @@ -3,8 +3,12 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable function-max-lines, gas-indexed-events, gas-strict-inequalities, use-natspec +// solhint-disable named-parameters-mapping + import { AddressUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; -import { ITokenGateway } from "./arbitrum/ITokenGateway.sol"; +import { ITokenGateway } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { L2GraphTokenLockManager } from "./L2GraphTokenLockManager.sol"; import { GraphTokenLockWallet } from "./GraphTokenLockWallet.sol"; @@ -38,12 +42,16 @@ contract L1GraphTokenLockTransferTool is OwnableInitializable, Initializable, Mi using SafeMathUpgradeable for uint256; /// Address of the L1 GRT token contract + // solhint-disable-next-line immutable-vars-naming IERC20 public immutable graphToken; /// Address of the L2GraphTokenLockWallet implementation in L2, used to compute L2 wallet addresses + // solhint-disable-next-line immutable-vars-naming address public immutable l2Implementation; /// Address of the L1GraphTokenGateway contract + // solhint-disable-next-line immutable-vars-naming ITokenGateway public immutable l1Gateway; /// Address of the Staking contract, used to pull ETH for L2 ticket gas + // solhint-disable-next-line immutable-vars-naming address payable public immutable staking; /// L2 lock manager for each L1 lock manager. /// L1 GraphTokenLockManager => L2GraphTokenLockManager diff --git a/packages/token-distribution/contracts/L2GraphTokenLockManager.sol b/packages/token-distribution/contracts/L2GraphTokenLockManager.sol index ee1c30a59..75a2da68c 100644 --- a/packages/token-distribution/contracts/L2GraphTokenLockManager.sol +++ b/packages/token-distribution/contracts/L2GraphTokenLockManager.sol @@ -3,10 +3,14 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events, use-natspec +// solhint-disable named-parameters-mapping + import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; -import { ICallhookReceiver } from "./ICallhookReceiver.sol"; +import { ICallhookReceiver } from "@graphprotocol/interfaces/contracts/contracts/gateway/ICallhookReceiver.sol"; import { GraphTokenLockManager } from "./GraphTokenLockManager.sol"; import { L2GraphTokenLockWallet } from "./L2GraphTokenLockWallet.sol"; @@ -42,8 +46,10 @@ contract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver { } /// Address of the L2GraphTokenGateway + // solhint-disable-next-line immutable-vars-naming address public immutable l2Gateway; /// Address of the L1 transfer tool contract (in L1, no aliasing) + // solhint-disable-next-line immutable-vars-naming address public immutable l1TransferTool; /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received) /// L1 address => L2 address diff --git a/packages/token-distribution/contracts/L2GraphTokenLockTransferTool.sol b/packages/token-distribution/contracts/L2GraphTokenLockTransferTool.sol index 01010a3a0..0ef769549 100644 --- a/packages/token-distribution/contracts/L2GraphTokenLockTransferTool.sol +++ b/packages/token-distribution/contracts/L2GraphTokenLockTransferTool.sol @@ -3,11 +3,14 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-strict-inequalities, use-natspec + import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { L2GraphTokenLockManager } from "./L2GraphTokenLockManager.sol"; import { L2GraphTokenLockWallet } from "./L2GraphTokenLockWallet.sol"; -import { ITokenGateway } from "./arbitrum/ITokenGateway.sol"; +import { ITokenGateway } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol"; /** * @title L2GraphTokenLockTransferTool contract @@ -16,10 +19,13 @@ import { ITokenGateway } from "./arbitrum/ITokenGateway.sol"; */ contract L2GraphTokenLockTransferTool { /// Address of the L2 GRT token + // solhint-disable-next-line immutable-vars-naming IERC20 public immutable graphToken; /// Address of the L2GraphTokenGateway + // solhint-disable-next-line immutable-vars-naming ITokenGateway public immutable l2Gateway; /// Address of the L1 GRT token (in L1, no aliasing) + // solhint-disable-next-line immutable-vars-naming address public immutable l1GraphToken; /// @dev Emitted when GRT is sent to L1 from a token lock diff --git a/packages/token-distribution/contracts/L2GraphTokenLockWallet.sol b/packages/token-distribution/contracts/L2GraphTokenLockWallet.sol index 905bee460..3fcba490a 100644 --- a/packages/token-distribution/contracts/L2GraphTokenLockWallet.sol +++ b/packages/token-distribution/contracts/L2GraphTokenLockWallet.sol @@ -3,6 +3,9 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { GraphTokenLockWallet } from "./GraphTokenLockWallet.sol"; diff --git a/packages/token-distribution/contracts/MathUtils.sol b/packages/token-distribution/contracts/MathUtils.sol index 742c52c37..22853c809 100644 --- a/packages/token-distribution/contracts/MathUtils.sol +++ b/packages/token-distribution/contracts/MathUtils.sol @@ -2,6 +2,9 @@ pragma solidity ^0.7.3; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + library MathUtils { function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; diff --git a/packages/token-distribution/contracts/MinimalProxyFactory.sol b/packages/token-distribution/contracts/MinimalProxyFactory.sol index ca1f03ee1..9da66d95e 100644 --- a/packages/token-distribution/contracts/MinimalProxyFactory.sol +++ b/packages/token-distribution/contracts/MinimalProxyFactory.sol @@ -2,6 +2,9 @@ pragma solidity ^0.7.3; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; diff --git a/packages/token-distribution/contracts/Ownable.sol b/packages/token-distribution/contracts/Ownable.sol index 73ec22821..4e45fcd25 100644 --- a/packages/token-distribution/contracts/Ownable.sol +++ b/packages/token-distribution/contracts/Ownable.sol @@ -2,6 +2,9 @@ pragma solidity ^0.7.3; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec, gas-small-strings + /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to diff --git a/packages/token-distribution/contracts/arbitrum/ITokenGateway.sol b/packages/token-distribution/contracts/arbitrum/ITokenGateway.sol deleted file mode 100644 index bf2968309..000000000 --- a/packages/token-distribution/contracts/arbitrum/ITokenGateway.sol +++ /dev/null @@ -1,75 +0,0 @@ -// 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 (pablo@edgeandnode.com) - * - */ - -pragma solidity ^0.7.3; -pragma experimental ABIEncoderV2; - -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 _amount, - uint256 _maxGas, - uint256 _gasPriceBid, - 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); -} diff --git a/packages/token-distribution/contracts/tests/BridgeMock.sol b/packages/token-distribution/contracts/tests/BridgeMock.sol index 643a20428..48bfbbec3 100644 --- a/packages/token-distribution/contracts/tests/BridgeMock.sol +++ b/packages/token-distribution/contracts/tests/BridgeMock.sol @@ -2,7 +2,10 @@ pragma solidity ^0.7.3; -import "./arbitrum/IBridge.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-increment-by-one, use-natspec + +import { IBridge } from "./arbitrum/IBridge.sol"; /** * @title Arbitrum Bridge mock contract diff --git a/packages/token-distribution/contracts/tests/GraphTokenMock.sol b/packages/token-distribution/contracts/tests/GraphTokenMock.sol index bc52b9456..f513c92d6 100644 --- a/packages/token-distribution/contracts/tests/GraphTokenMock.sol +++ b/packages/token-distribution/contracts/tests/GraphTokenMock.sol @@ -2,8 +2,11 @@ pragma solidity ^0.7.3; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; /** * @title Graph Token Mock contract. diff --git a/packages/token-distribution/contracts/tests/InboxMock.sol b/packages/token-distribution/contracts/tests/InboxMock.sol index 9c16ee4ab..fa6b28c82 100644 --- a/packages/token-distribution/contracts/tests/InboxMock.sol +++ b/packages/token-distribution/contracts/tests/InboxMock.sol @@ -2,8 +2,12 @@ pragma solidity ^0.7.3; -import "./arbitrum/IInbox.sol"; -import "./arbitrum/AddressAliasHelper.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + +import { IInbox } from "./arbitrum/IInbox.sol"; +import { AddressAliasHelper } from "./arbitrum/AddressAliasHelper.sol"; +import { IBridge } from "./arbitrum/IBridge.sol"; /** * @title Arbitrum Inbox mock contract diff --git a/packages/token-distribution/contracts/tests/L1TokenGatewayMock.sol b/packages/token-distribution/contracts/tests/L1TokenGatewayMock.sol index 679bcb0ad..fdbab7bcb 100644 --- a/packages/token-distribution/contracts/tests/L1TokenGatewayMock.sol +++ b/packages/token-distribution/contracts/tests/L1TokenGatewayMock.sol @@ -2,10 +2,12 @@ pragma solidity ^0.7.3; +// solhint-disable gas-increment-by-one, gas-indexed-events, gas-strict-inequalities, use-natspec + import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; -import { ITokenGateway } from "../arbitrum//ITokenGateway.sol"; +import { ITokenGateway } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol"; /** * @title L1 Token Gateway mock contract diff --git a/packages/token-distribution/contracts/tests/L2TokenGatewayMock.sol b/packages/token-distribution/contracts/tests/L2TokenGatewayMock.sol index c9e12dd74..02a5383e4 100644 --- a/packages/token-distribution/contracts/tests/L2TokenGatewayMock.sol +++ b/packages/token-distribution/contracts/tests/L2TokenGatewayMock.sol @@ -2,10 +2,12 @@ pragma solidity ^0.7.3; +// solhint-disable gas-increment-by-one, gas-indexed-events, use-natspec + import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { ITokenGateway } from "../arbitrum//ITokenGateway.sol"; +import { ITokenGateway } from "@graphprotocol/interfaces/contracts/contracts/arbitrum/ITokenGateway.sol"; import { GraphTokenMock } from "./GraphTokenMock.sol"; -import { ICallhookReceiver } from "../ICallhookReceiver.sol"; +import { ICallhookReceiver } from "@graphprotocol/interfaces/contracts/contracts/gateway/ICallhookReceiver.sol"; /** * @title L2 Token Gateway mock contract @@ -13,8 +15,10 @@ import { ICallhookReceiver } from "../ICallhookReceiver.sol"; */ contract L2TokenGatewayMock is Ownable { /// Address of the L1 GRT contract + // solhint-disable-next-line immutable-vars-naming address public immutable l1Token; /// Address of the L2 GRT contract + // solhint-disable-next-line immutable-vars-naming address public immutable l2Token; /// Next ID to return when sending an outboundTransfer uint256 public nextId; diff --git a/packages/token-distribution/contracts/tests/Stakes.sol b/packages/token-distribution/contracts/tests/Stakes.sol index bf140aa8f..81d5480fa 100644 --- a/packages/token-distribution/contracts/tests/Stakes.sol +++ b/packages/token-distribution/contracts/tests/Stakes.sol @@ -3,7 +3,10 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; -import "@openzeppelin/contracts/math/SafeMath.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; /** * @title A collection of data structures and functions to manage the Indexer Stake state. diff --git a/packages/token-distribution/contracts/tests/StakingMock.sol b/packages/token-distribution/contracts/tests/StakingMock.sol index 8c5fffc80..b4c1871ed 100644 --- a/packages/token-distribution/contracts/tests/StakingMock.sol +++ b/packages/token-distribution/contracts/tests/StakingMock.sol @@ -3,48 +3,71 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +// solhint-disable named-parameters-mapping +// solhint-disable gas-strict-inequalities -import "./Stakes.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; +import { Stakes } from "./Stakes.sol"; + +/** + * @title StakingMock contract + * @author Edge & Node + * @notice A mock contract for testing staking functionality + */ contract StakingMock { using SafeMath for uint256; using Stakes for Stakes.Indexer; // -- State -- + /// @notice Minimum stake required for indexers uint256 public minimumIndexerStake = 100e18; + /// @notice Thawing period in blocks uint256 public thawingPeriod = 10; // 10 blocks + /// @notice The token contract IERC20 public token; - // Indexer stakes : indexer => Stake + /// @notice Indexer stakes mapping mapping(address => Stakes.Indexer) public stakes; /** - * @dev Emitted when `indexer` stake `tokens` amount. + * @notice Emitted when indexer stakes tokens + * @param indexer The indexer address + * @param tokens The amount of tokens staked */ - event StakeDeposited(address indexed indexer, uint256 tokens); + event StakeDeposited(address indexed indexer, uint256 indexed tokens); /** - * @dev Emitted when `indexer` unstaked and locked `tokens` amount `until` block. + * @notice Emitted when indexer unstakes and locks tokens + * @param indexer The indexer address + * @param tokens The amount of tokens locked + * @param until The block number until which tokens are locked */ - event StakeLocked(address indexed indexer, uint256 tokens, uint256 until); + event StakeLocked(address indexed indexer, uint256 indexed tokens, uint256 indexed until); /** - * @dev Emitted when `indexer` withdrew `tokens` staked. + * @notice Emitted when indexer withdraws staked tokens + * @param indexer The indexer address + * @param tokens The amount of tokens withdrawn */ - event StakeWithdrawn(address indexed indexer, uint256 tokens); + event StakeWithdrawn(address indexed indexer, uint256 indexed tokens); - // Contract constructor. + /** + * @notice Contract constructor + * @param _token The token contract address + */ constructor(IERC20 _token) { require(address(_token) != address(0), "!token"); token = _token; } + /// @notice Receive function to accept ETH receive() external payable {} /** - * @dev Deposit tokens on the indexer stake. + * @notice Deposit tokens on the indexer stake * @param _tokens Amount of tokens to stake */ function stake(uint256 _tokens) external { @@ -52,7 +75,7 @@ contract StakingMock { } /** - * @dev Deposit tokens on the indexer stake. + * @notice Deposit tokens on the indexer stake * @param _indexer Address of the indexer * @param _tokens Amount of tokens to stake */ @@ -70,7 +93,7 @@ contract StakingMock { } /** - * @dev Unstake tokens from the indexer stake, lock them until thawing period expires. + * @notice Unstake tokens from the indexer stake, lock them until thawing period expires * @param _tokens Amount of tokens to unstake */ function unstake(uint256 _tokens) external { @@ -97,12 +120,17 @@ contract StakingMock { } /** - * @dev Withdraw indexer tokens once the thawing period has passed. + * @notice Withdraw indexer tokens once the thawing period has passed */ function withdraw() external { _withdraw(msg.sender); } + /** + * @notice Internal function to stake tokens for an indexer + * @param _indexer Address of the indexer + * @param _tokens Amount of tokens to stake + */ function _stake(address _indexer, uint256 _tokens) internal { // Deposit tokens into the indexer stake Stakes.Indexer storage indexerStake = stakes[_indexer]; @@ -112,7 +140,7 @@ contract StakingMock { } /** - * @dev Withdraw indexer tokens once the thawing period has passed. + * @notice Withdraw indexer tokens once the thawing period has passed * @param _indexer Address of indexer to withdraw funds from */ function _withdraw(address _indexer) private { diff --git a/packages/token-distribution/contracts/tests/WalletMock.sol b/packages/token-distribution/contracts/tests/WalletMock.sol index 872760d6e..b526e547b 100644 --- a/packages/token-distribution/contracts/tests/WalletMock.sol +++ b/packages/token-distribution/contracts/tests/WalletMock.sol @@ -3,6 +3,9 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + import { Address } from "@openzeppelin/contracts/utils/Address.sol"; /** @@ -14,14 +17,19 @@ import { Address } from "@openzeppelin/contracts/utils/Address.sol"; */ contract WalletMock { /// Target contract for the fallback function (usually a transfer tool contract) + // solhint-disable-next-line immutable-vars-naming address public immutable target; /// Address of the GRT (mock) token + // solhint-disable-next-line immutable-vars-naming address public immutable token; /// Address of the wallet's manager + // solhint-disable-next-line immutable-vars-naming address public immutable manager; /// Whether the wallet has been initialized + // solhint-disable-next-line immutable-vars-naming bool public immutable isInitialized; /// Whether the beneficiary has accepted the lock + // solhint-disable-next-line immutable-vars-naming bool public immutable isAccepted; /** diff --git a/packages/token-distribution/contracts/tests/arbitrum/AddressAliasHelper.sol b/packages/token-distribution/contracts/tests/arbitrum/AddressAliasHelper.sol index 146c1c876..525e71640 100644 --- a/packages/token-distribution/contracts/tests/arbitrum/AddressAliasHelper.sol +++ b/packages/token-distribution/contracts/tests/arbitrum/AddressAliasHelper.sol @@ -25,8 +25,12 @@ pragma solidity ^0.7.3; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + library AddressAliasHelper { - uint160 constant offset = uint160(0x1111000000000000000000000000000000001111); + // solhint-disable-next-line const-name-snakecase + uint160 internal constant offset = uint160(0x1111000000000000000000000000000000001111); /// @notice Utility function that converts the address in the L1 that submitted a tx to /// the inbox to the msg.sender viewed in the L2 diff --git a/packages/token-distribution/contracts/tests/arbitrum/IBridge.sol b/packages/token-distribution/contracts/tests/arbitrum/IBridge.sol index fdfa34eed..f4ace5767 100644 --- a/packages/token-distribution/contracts/tests/arbitrum/IBridge.sol +++ b/packages/token-distribution/contracts/tests/arbitrum/IBridge.sol @@ -25,6 +25,9 @@ pragma solidity ^0.7.3; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec, gas-indexed-events + interface IBridge { event MessageDelivered( uint256 indexed messageIndex, diff --git a/packages/token-distribution/contracts/tests/arbitrum/IInbox.sol b/packages/token-distribution/contracts/tests/arbitrum/IInbox.sol index 0a6e78dc3..a3b7b096a 100644 --- a/packages/token-distribution/contracts/tests/arbitrum/IInbox.sol +++ b/packages/token-distribution/contracts/tests/arbitrum/IInbox.sol @@ -25,8 +25,11 @@ pragma solidity ^0.7.3; -import "./IBridge.sol"; -import "./IMessageProvider.sol"; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + +import { IBridge } from "./IBridge.sol"; +import { IMessageProvider } from "./IMessageProvider.sol"; interface IInbox is IMessageProvider { function sendL2Message(bytes calldata messageData) external returns (uint256); diff --git a/packages/token-distribution/contracts/tests/arbitrum/IMessageProvider.sol b/packages/token-distribution/contracts/tests/arbitrum/IMessageProvider.sol index cf8446af2..28b3937e8 100644 --- a/packages/token-distribution/contracts/tests/arbitrum/IMessageProvider.sol +++ b/packages/token-distribution/contracts/tests/arbitrum/IMessageProvider.sol @@ -25,6 +25,9 @@ pragma solidity ^0.7.3; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + interface IMessageProvider { event InboxMessageDelivered(uint256 indexed messageNum, bytes data); diff --git a/packages/token-distribution/package.json b/packages/token-distribution/package.json index f02699c4b..21019d6e6 100644 --- a/packages/token-distribution/package.json +++ b/packages/token-distribution/package.json @@ -46,6 +46,7 @@ "@ethersproject/providers": "^5.7.0", "@graphprotocol/client-cli": "^2.2.22", "@graphprotocol/contracts": "workspace:^", + "@graphprotocol/interfaces": "workspace:^", "@graphql-yoga/plugin-persisted-operations": "^3.13.5", "@nomiclabs/hardhat-ethers": "^2.2.3", "@nomiclabs/hardhat-etherscan": "^3.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1661a294a..cd273a1ba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1106,6 +1106,9 @@ importers: '@graphprotocol/contracts': specifier: workspace:^ version: link:../contracts + '@graphprotocol/interfaces': + specifier: workspace:^ + version: link:../interfaces '@graphql-yoga/plugin-persisted-operations': specifier: ^3.13.5 version: 3.16.0(graphql-yoga@5.16.0(graphql@16.11.0))(graphql@16.11.0)