From 0420c169a232add2938cceb04cbe60c74465834f Mon Sep 17 00:00:00 2001 From: Rembrandt Kuipers Date: Wed, 13 Aug 2025 12:02:55 +0000 Subject: [PATCH 1/4] fix(pnpm): ignore .pnpm-store/ --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 139aa27bf..ade4d48bf 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ node.log node_modules/ forge-std/ **/lib/forge-std/ +.pnpm-store/ # Yarn .yarn/* From 1eec283427bc7860758b2cc076c2e27b5354f31b Mon Sep 17 00:00:00 2001 From: Rembrandt Kuipers Date: Wed, 13 Aug 2025 12:04:23 +0000 Subject: [PATCH 2/4] feat(container): ugrade dev container to use Claude, /work dir, and JSON5 --- .devcontainer/Dockerfile | 3 +++ .devcontainer/devcontainer.json | 8 ++++++-- .devcontainer/docker-compose.yml | 4 ++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 9c542e4d9..221072795 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -47,6 +47,9 @@ RUN npm install -g ethers@6.13.4 # Install cloc for code analysis RUN npm install -g cloc +# Install Claude Code +RUN npm install -g @anthropic-ai/claude-code + # Install Foundry for Anvil (as root for global installation) RUN curl -L https://foundry.paradigm.xyz | bash && \ /root/.foundry/bin/foundryup && \ diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 8d7fb643d..3d619eab0 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -16,9 +16,12 @@ }, "postCreateCommand": ".devcontainer/project-setup.sh", "remoteUser": "vscode", - "workspaceFolder": "${localWorkspaceFolder}", + "workspaceFolder": "/work", "customizations": { "vscode": { + "settings": { + "terminal.integrated.cwd": "/work" + }, "extensions": [ "rust-lang.rust-analyzer", "tamasfe.even-better-toml", @@ -35,7 +38,8 @@ "streetsidesoftware.code-spell-checker", "Augment.vscode-augment", "NomicFoundation.hardhat-solidity", - "foundry-rs.foundry-vscode" + "foundry-rs.foundry-vscode", + "BlueGlassBlock.better-json5" ] } } diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index d16a44b34..824bb9baf 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -3,6 +3,8 @@ services: build: context: . dockerfile: Dockerfile + user: vscode + working_dir: /work env_file: - /opt/configs/graphprotocol/contracts.env environment: @@ -31,6 +33,8 @@ services: # Note: NPM, Foundry, and Solidity caches are intentionally not set # to avoid cross-branch contamination. Tools will use their default locations. volumes: + - ..:/work + # Git repo root - /git:/git From 85bc48fb5d079cb6d475eaf9409e4d21bd9bca12 Mon Sep 17 00:00:00 2001 From: Rembrandt Kuipers Date: Thu, 14 Aug 2025 08:47:30 +0000 Subject: [PATCH 3/4] feat: upgrade of pnpm, linting, package dependencies, and linting fixes --- .github/workflows/build-test.yml | 2 +- .github/workflows/lint.yml | 18 - .gitignore | 10 +- .markdownlint.json | 11 +- .markdownlintignore | 37 + .prettierignore | 5 +- README.md | 163 ++- eslint.config.mjs | 24 +- package.json | 28 +- packages/common/.solhint.json | 3 + .../contracts/rewards/IRewardsManager.sol | 15 +- .../common/contracts/token/IGraphToken.sol | 3 + packages/common/package.json | 27 +- packages/contracts/.solhint.json | 3 + .../contracts/arbitrum/AddressAliasHelper.sol | 9 +- .../contracts/arbitrum/IArbToken.sol | 10 + .../contracts/contracts/arbitrum/IBridge.sol | 83 +- .../contracts/contracts/arbitrum/IInbox.sol | 83 +- .../contracts/arbitrum/IMessageProvider.sol | 14 + .../contracts/contracts/arbitrum/IOutbox.sol | 57 + .../contracts/arbitrum/ITokenGateway.sol | 45 +- .../arbitrum/L1ArbitrumMessenger.sol | 62 +- .../arbitrum/L2ArbitrumMessenger.sol | 26 +- .../contracts/bancor/BancorFormula.sol | 76 +- .../contracts/contracts/base/IMulticall.sol | 1 + .../contracts/contracts/base/Multicall.sol | 9 +- .../contracts/contracts/curation/Curation.sol | 44 +- .../contracts/curation/CurationStorage.sol | 25 +- .../contracts/curation/GraphCurationToken.sol | 13 +- .../contracts/curation/ICuration.sol | 7 +- .../curation/IGraphCurationToken.sol | 21 +- .../contracts/contracts/discovery/GNS.sol | 183 +-- .../contracts/discovery/GNSStorage.sol | 21 +- .../contracts/contracts/discovery/IGNS.sol | 16 +- .../contracts/discovery/IServiceRegistry.sol | 33 + .../contracts/discovery/ISubgraphNFT.sol | 44 +- .../discovery/ISubgraphNFTDescriptor.sol | 6 +- .../contracts/contracts/discovery/L1GNS.sol | 25 +- .../contracts/discovery/L1GNSStorage.sol | 3 +- .../contracts/discovery/ServiceRegistry.sol | 50 +- .../discovery/ServiceRegistryStorage.sol | 10 +- .../contracts/discovery/SubgraphNFT.sol | 76 +- .../discovery/SubgraphNFTDescriptor.sol | 10 +- .../discovery/erc1056/EthereumDIDRegistry.sol | 173 +++ .../erc1056/IEthereumDIDRegistry.sol | 17 + .../contracts/disputes/DisputeManager.sol | 207 ++-- .../disputes/DisputeManagerStorage.sol | 29 +- .../contracts/disputes/IDisputeManager.sol | 118 +- .../contracts/epochs/EpochManager.sol | 62 +- .../contracts/epochs/EpochManagerStorage.sol | 14 +- .../contracts/epochs/IEpochManager.sol | 47 + .../contracts/gateway/BridgeEscrow.sol | 3 +- .../contracts/gateway/GraphTokenGateway.sol | 7 +- .../contracts/gateway/ICallhookReceiver.sol | 8 +- .../contracts/gateway/L1GraphTokenGateway.sol | 132 ++- .../contracts/governance/Controller.sol | 50 +- .../contracts/governance/Governed.sol | 28 +- .../contracts/governance/IController.sol | 50 + .../contracts/governance/IManaged.sol | 12 +- .../contracts/governance/Managed.sol | 72 +- .../contracts/governance/Pausable.sol | 38 +- .../contracts/l2/curation/IL2Curation.sol | 2 + .../contracts/l2/curation/L2Curation.sol | 64 +- .../contracts/l2/discovery/IL2GNS.sol | 11 + .../contracts/l2/discovery/L2GNS.sol | 56 +- .../contracts/l2/discovery/L2GNSStorage.sol | 4 +- .../l2/gateway/L2GraphTokenGateway.sol | 79 +- .../contracts/l2/staking/IL2Staking.sol | 12 +- .../contracts/l2/staking/IL2StakingBase.sol | 10 + .../contracts/l2/staking/L2Staking.sol | 21 +- .../l2/token/GraphTokenUpgradeable.sol | 27 +- .../contracts/l2/token/L2GraphToken.sol | 45 +- .../contracts/libraries/Base58Encoder.sol | 39 +- .../contracts/libraries/HexStrings.sol | 21 +- .../contracts/payments/AllocationExchange.sol | 62 +- .../contracts/rewards/RewardsManager.sol | 88 +- .../rewards/RewardsManagerStorage.sol | 36 +- .../rewards/SubgraphAvailabilityManager.sol | 43 +- .../staking/IL1GraphTokenLockTransferTool.sol | 3 +- .../contracts/staking/IL1Staking.sol | 1 + .../contracts/staking/IL1StakingBase.sol | 33 +- .../contracts/contracts/staking/IStaking.sol | 1 + .../contracts/staking/IStakingBase.sol | 74 +- .../contracts/staking/IStakingData.sol | 26 +- .../contracts/staking/IStakingExtension.sol | 42 +- .../contracts/contracts/staking/L1Staking.sol | 90 +- .../contracts/staking/L1StakingStorage.sol | 3 +- .../contracts/contracts/staking/Staking.sol | 180 +-- .../contracts/staking/StakingExtension.sol | 161 +-- .../contracts/staking/StakingStorage.sol | 14 +- .../contracts/staking/libs/Exponential.sol | 3 +- .../contracts/staking/libs/LibFixedMath.sol | 111 +- .../contracts/staking/libs/MathUtils.sol | 19 +- .../contracts/staking/libs/Stakes.sol | 39 +- .../contracts/tests/CallhookReceiverMock.sol | 22 +- .../contracts/tests/GovernedMock.sol | 9 +- .../L1GraphTokenLockTransferToolBadMock.sol | 17 +- .../L1GraphTokenLockTransferToolMock.sol | 16 + .../contracts/tests/LegacyGNSMock.sol | 3 + .../contracts/tests/arbitrum/ArbSysMock.sol | 10 + .../contracts/tests/arbitrum/BridgeMock.sol | 57 +- .../contracts/tests/arbitrum/InboxMock.sol | 49 +- .../contracts/tests/arbitrum/OutboxMock.sol | 52 +- .../contracts/contracts/tests/ens/IENS.sol | 24 +- .../contracts/tests/ens/IPublicResolver.sol | 19 + .../contracts/tests/ens/ITestRegistrar.sol | 12 + .../contracts/contracts/token/GraphToken.sol | 64 +- .../contracts/upgrades/GraphProxy.sol | 52 +- .../contracts/upgrades/GraphProxyAdmin.sol | 5 +- .../contracts/upgrades/GraphProxyStorage.sol | 28 +- .../contracts/upgrades/GraphUpgradeable.sol | 8 +- .../contracts/upgrades/IGraphProxy.sol | 58 + .../contracts/contracts/utils/TokenUtils.sol | 15 +- packages/contracts/package.json | 31 +- packages/contracts/task/package.json | 1 - packages/contracts/task/prettier.config.cjs | 5 + packages/contracts/test/hardhat.config.ts | 60 +- packages/contracts/test/package.json | 7 +- packages/contracts/test/prettier.config.cjs | 5 + .../tests/unit/governance/governed.test.ts | 4 +- .../tests/unit/l2/l2GraphTokenGateway.test.ts | 32 +- .../test/tests/unit/rewards/rewards.test.ts | 10 +- .../tests/unit/staking/configuration.test.ts | 6 +- packages/data-edge/.solhint.json | 3 + packages/data-edge/contracts/DataEdge.sol | 4 +- .../data-edge/contracts/EventfulDataEdge.sol | 5 + packages/data-edge/package.json | 18 +- packages/sdk/package.json | 36 +- .../network/deployment/contracts/load.ts | 2 +- packages/sdk/src/gre/test/accounts.test.ts | 6 +- packages/sdk/src/gre/test/config.test.ts | 12 +- .../gre/test/files/config/graph.goerli.yml | 12 +- packages/sdk/src/gre/test/gre.test.ts | 2 +- packages/sdk/tsconfig.json | 4 +- .../.graphclient-extracted/index.d.ts | 552 +++++++++ .../.graphclient-extracted/index.js | 103 ++ packages/token-distribution/.solhint.json | 3 + .../contracts/GraphTokenDistributor.sol | 11 +- .../contracts/GraphTokenLock.sol | 29 +- .../contracts/GraphTokenLockManager.sol | 16 +- .../contracts/GraphTokenLockSimple.sol | 9 +- .../contracts/GraphTokenLockWallet.sol | 25 +- .../contracts/ICallhookReceiver.sol | 3 + .../contracts/IGraphTokenLock.sol | 3 +- .../contracts/IGraphTokenLockManager.sol | 7 +- .../L1GraphTokenLockTransferTool.sol | 7 + .../contracts/L2GraphTokenLockManager.sol | 5 + .../L2GraphTokenLockTransferTool.sol | 6 + .../contracts/L2GraphTokenLockWallet.sol | 3 + .../contracts/MathUtils.sol | 3 + .../contracts/MinimalProxyFactory.sol | 3 + .../token-distribution/contracts/Ownable.sol | 3 + .../contracts/arbitrum/ITokenGateway.sol | 3 + .../contracts/tests/BridgeMock.sol | 5 +- .../contracts/tests/GraphTokenMock.sol | 7 +- .../contracts/tests/InboxMock.sol | 8 +- .../contracts/tests/L1TokenGatewayMock.sol | 2 + .../contracts/tests/L2TokenGatewayMock.sol | 4 + .../contracts/tests/Stakes.sol | 5 +- .../contracts/tests/StakingMock.sol | 7 +- .../contracts/tests/WalletMock.sol | 8 + .../tests/arbitrum/AddressAliasHelper.sol | 6 +- .../contracts/tests/arbitrum/IBridge.sol | 3 + .../contracts/tests/arbitrum/IInbox.sol | 7 +- .../tests/arbitrum/IMessageProvider.sol | 3 + packages/token-distribution/ops/info.ts | 4 +- packages/token-distribution/package.json | 26 +- packages/token-distribution/scripts/build.js | 67 +- .../scripts/extract-graphclient.js | 190 +++ pnpm-lock.yaml | 1047 +++++++++-------- pnpm-workspace.yaml | 49 +- scripts/check-todos.sh | 78 ++ scripts/lint-staged-run.sh | 51 + scripts/verify-solhint-disables.js | 299 +++++ tsconfig.json | 7 +- 175 files changed, 5279 insertions(+), 2081 deletions(-) create mode 100644 .markdownlintignore create mode 100644 packages/common/.solhint.json create mode 100644 packages/contracts/.solhint.json create mode 100644 packages/contracts/task/prettier.config.cjs create mode 100644 packages/contracts/test/prettier.config.cjs create mode 100644 packages/data-edge/.solhint.json create mode 100644 packages/token-distribution/.graphclient-extracted/index.d.ts create mode 100644 packages/token-distribution/.graphclient-extracted/index.js create mode 100644 packages/token-distribution/.solhint.json create mode 100644 packages/token-distribution/scripts/extract-graphclient.js create mode 100755 scripts/check-todos.sh create mode 100755 scripts/lint-staged-run.sh create mode 100755 scripts/verify-solhint-disables.js diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 3450ef3bd..5ca3b2fcd 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -47,4 +47,4 @@ jobs: files: ${{ steps.coverage_files.outputs.files }} flags: unittests name: graphprotocol-contracts - fail_ci_if_error: true + fail_ci_if_error: false diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index db28bb954..7746988af 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -167,15 +167,6 @@ jobs: echo "sol_prettier_exit_code=0" >> $GITHUB_OUTPUT fi - - name: Lint Solidity files (Natspec Documentation) - id: lint_sol_natspec - continue-on-error: true - run: | - echo "Checking Solidity documentation with natspec-smells..." - # Run natspec-smells from root to check all configured packages - npx natspec-smells - echo "sol_natspec_exit_code=$?" >> $GITHUB_OUTPUT - - name: Lint Markdown files (Markdownlint) id: lint_md_markdownlint continue-on-error: true @@ -320,15 +311,6 @@ jobs: WARNINGS=$((WARNINGS+1)) fi - # Solidity - Natspec Documentation - if [ "$SOL_NATSPEC_EXIT_CODE" = "1" ]; then - echo "::error::natspec-smells found documentation issues in Solidity files" - ERRORS=$((ERRORS+1)) - elif [ "$SOL_NATSPEC_EXIT_CODE" != "0" ]; then - echo "::warning::natspec-smells found warnings in Solidity files" - WARNINGS=$((WARNINGS+1)) - fi - # Markdown - Markdownlint if [ "$MD_MARKDOWNLINT_EXIT_CODE" = "1" ]; then echo "::error::Markdownlint found errors in Markdown files" diff --git a/.gitignore b/.gitignore index ade4d48bf..51086e4bd 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,6 @@ node.log # Dependency directories node_modules/ -forge-std/ -**/lib/forge-std/ .pnpm-store/ # Yarn @@ -30,8 +28,12 @@ packages/*/.eslintcache # Build artifacts dist/ build/ +typechain/ +typechain-types/ types/ deployments/hardhat/ +*.js.map +*.d.ts.map # TypeScript incremental compilation cache **/tsconfig.tsbuildinfo @@ -52,13 +54,12 @@ lcov.info hardhat-dependency-compiler/ # Local test files -addresses-local.json +addresses-local*.json localNetwork.json arbitrum-addresses-local.json tx-*.log addresses-fork.json addresses-hardhat.json -addresses-local-network.json # Keys .keystore @@ -67,7 +68,6 @@ addresses-local-network.json cache_forge forge-artifacts/ out/ -packages/issuance/lib/forge-std/ # Graph client .graphclient diff --git a/.markdownlint.json b/.markdownlint.json index 5b37d3bd4..66420fefa 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -1,9 +1,14 @@ { "default": true, + "MD004": { "style": "dash" }, + "MD007": { "indent": 2 }, "MD013": false, + "MD022": false, "MD024": { "siblings_only": true }, - "MD033": false, "MD029": { "style": "ordered" }, - "MD007": { "indent": 2 }, - "MD004": { "style": "dash" } + "MD031": false, + "MD032": false, + "MD033": false, + "MD040": false, + "MD047": false } diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 000000000..7e6987fa7 --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,37 @@ +# Autogenerated GraphClient files (committed but should not be linted) +**/.graphclient-extracted/ +**/.graphclient/ + +# Dependencies (from .gitignore patterns) +node_modules/ +lib/ + +# Build outputs that might contain markdown +**/build/ +**/dist/ +**/artifacts/ +**/typechain-types/ +**/types/ +**/cache/ +**/cached/ +cache +typechain/ +bin/ +forge-artifacts/ +out/ + +# Coverage and reports +coverage/ +reports/ +coverage.json +lcov.info +.nyc_output/ + +# Other generated files +.eslintcache +packages/*/.eslintcache +deployments/hardhat/ +.graphclient +**/chain-*/ +**/*-localhost/ +**/*-hardhat/ diff --git a/.prettierignore b/.prettierignore index cf4392420..392204805 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,7 +5,9 @@ yarn.lock # Dependencies (from .gitignore) node_modules/ -forge-std/ + +# Third-party libraries in lib directories +**/lib/ # Build outputs (from .gitignore) **/build/ @@ -33,6 +35,7 @@ lcov.info packages/*/.eslintcache deployments/hardhat/ .graphclient +**/.graphclient-extracted/ **/chain-31337/ **/chain-1377/ **/horizon-localhost/ diff --git a/README.md b/README.md index fd7cb8047..57236c500 100644 --- a/README.md +++ b/README.md @@ -35,13 +35,13 @@ This repository is a pnpm workspaces monorepo containing the following packages: | Package | Latest version | Description | | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- | +| [common](./packages/common) | [![npm version](https://badge.fury.io/js/@graphprotocol%2Fcommon.svg)](https://badge.fury.io/js/@graphprotocol%2Fcommon) | Common utilities and configuration for Graph Protocol packages | | [contracts](./packages/contracts) | [![npm version](https://badge.fury.io/js/@graphprotocol%2Fcontracts.svg)](https://badge.fury.io/js/@graphprotocol%2Fcontracts) | Contracts enabling the open and permissionless decentralized network known as The Graph protocol. | +| [data-edge](./packages/data-edge) | [![npm version](https://badge.fury.io/js/@graphprotocol%2Fdata-edge.svg)](https://badge.fury.io/js/@graphprotocol%2Fdata-edge) | Data edge testing and utilities for The Graph protocol | | [horizon](./packages/horizon) | - | Contracts for Graph Horizon, the next iteration of The Graph protocol. | -| [token-distribution](./packages/token-distribution) | [![npm version](https://badge.fury.io/js/@graphprotocol%2Ftoken-distribution.svg)](https://badge.fury.io/js/@graphprotocol%2Ftoken-distribution) | Contracts managing token locks for network participants | -| [sdk](./packages/sdk) | [![npm version](https://badge.fury.io/js/@graphprotocol%2Fsdk.svg)](https://badge.fury.io/js/@graphprotocol%2Fsdk) | TypeScript based SDK to interact with the protocol contracts | | [issuance](./packages/issuance) | [![npm version](https://badge.fury.io/js/@graphprotocol%2Fissuance.svg)](https://badge.fury.io/js/@graphprotocol%2Fissuance) | Smart contracts for The Graph's token issuance functionality | -| [data-edge](./packages/data-edge) | [![npm version](https://badge.fury.io/js/@graphprotocol%2Fdata-edge.svg)](https://badge.fury.io/js/@graphprotocol%2Fdata-edge) | Data edge testing and utilities for The Graph protocol | -| [common](./packages/common) | [![npm version](https://badge.fury.io/js/@graphprotocol%2Fcommon.svg)](https://badge.fury.io/js/@graphprotocol%2Fcommon) | Common utilities and configuration for Graph Protocol packages | +| [sdk](./packages/sdk) | [![npm version](https://badge.fury.io/js/@graphprotocol%2Fsdk.svg)](https://badge.fury.io/js/@graphprotocol%2Fsdk) | TypeScript based SDK to interact with the protocol contracts | +| [token-distribution](./packages/token-distribution) | [![npm version](https://badge.fury.io/js/@graphprotocol%2Ftoken-distribution.svg)](https://badge.fury.io/js/@graphprotocol%2Ftoken-distribution) | Contracts managing token locks for network participants | ## Development @@ -117,6 +117,161 @@ pnpm publish --recursive Alternatively, there is a GitHub action that can be manually triggered to publish a package. +## Linting Configuration + +This monorepo uses a comprehensive linting setup with multiple tools to ensure code quality and consistency across all packages. + +### Linting Tools Overview + +- **ESLint**: JavaScript/TypeScript code quality and style enforcement +- **Prettier**: Code formatting for JavaScript, TypeScript, JSON, Markdown, YAML, and Solidity +- **Solhint**: Solidity-specific linting for smart contracts +- **Markdownlint**: Markdown formatting and style consistency +- **YAML Lint**: YAML file validation and formatting +- **NatSpec Smells**: Documentation quality checks for Solidity contracts + +### Configuration Architecture + +The linting configuration follows a hierarchical structure where packages inherit from root-level configurations: + +#### ESLint Configuration + +- **Root Configuration**: `eslint.config.mjs` - Modern flat config format +- **Direct Command**: `npx eslint '**/*.{js,ts,cjs,mjs,jsx,tsx}' --fix` +- **Behavior**: ESLint automatically searches up parent directories to find configuration files +- **Package Inheritance**: Packages automatically inherit the root ESLint configuration without needing local config files +- **Global Ignores**: Configured to exclude autogenerated files (`.graphclient-extracted/`, `lib/`) and build outputs + +#### Prettier Configuration + +- **Root Configuration**: `prettier.config.cjs` - Base formatting rules for all file types +- **Direct Command**: `npx prettier -w --cache '**/*.{js,ts,cjs,mjs,jsx,tsx,json,md,sol,yml,yaml}'` +- **Package Inheritance**: Packages that need Prettier must have a `prettier.config.cjs` file that inherits from the shared config +- **Example Package Config**: + + ```javascript + const baseConfig = require('../../prettier.config.cjs') + module.exports = { ...baseConfig } + ``` + +- **Ignore Files**: `.prettierignore` excludes lock files, build outputs, and third-party dependencies + +#### Solidity Linting (Solhint) + +- **Root Configuration**: `.solhint.json` - Base Solidity linting rules extending `solhint:recommended` +- **Direct Command**: `npx solhint 'contracts/**/*.sol'` (add `--fix` for auto-fixing) +- **List Applied Rules**: `npx solhint list-rules` +- **TODO Comment Checking**: `scripts/check-todos.sh` - Blocks commits and linting if TODO/FIXME/XXX/HACK comments are found in changed Solidity files +- **Package Inheritance**: Packages can extend the root config with package-specific rules +- **Configuration Inheritance Limitation**: Solhint has a limitation where nested `extends` don't work properly. When a local config extends a parent config that itself extends `solhint:recommended`, the built-in ruleset is ignored. +- **Recommended Package Extension Pattern**: + + ```json + { + "extends": ["solhint:recommended", "./../../.solhint.json"], + "rules": { + "no-console": "off", + "import-path-check": "off" + } + } + ``` + +#### Markdown Linting (Markdownlint) + +- **Root Configuration**: `.markdownlint.json` - Markdown formatting and style rules +- **Direct Command**: `npx markdownlint '**/*.md' --fix` +- **Ignore Files**: `.markdownlintignore` automatically picked up by markdownlint CLI +- **Global Application**: Applied to all markdown files across the monorepo + +### Linting Scripts + +#### Root Level Scripts + +```bash +# Run all linting tools +pnpm lint + +# Individual linting commands +pnpm lint:ts # ESLint + Prettier for TypeScript/JavaScript +pnpm lint:sol # TODO check + Solhint + Prettier for Solidity (runs recursively) +pnpm lint:md # Markdownlint + Prettier for Markdown +pnpm lint:json # Prettier for JSON files +pnpm lint:yaml # YAML linting + Prettier + +# Lint only staged files (useful for manual pre-commit checks) +pnpm lint:staged # Run linting on git-staged files only +``` + +#### Package Level Scripts + +Each package can define its own linting scripts that work with the inherited configurations: + +```bash +# Example from packages/contracts +pnpm lint:sol # Solhint for contracts in this package only +pnpm lint:ts # ESLint for TypeScript files in this package +``` + +### Pre-commit Hooks (lint-staged) + +The repository uses `lint-staged` with Husky to run linting on staged files before commits: + +- **Automatic**: Runs automatically on `git commit` via Husky pre-commit hook +- **Manual**: Run `pnpm lint:staged` to manually check staged files before committing +- **Configuration**: Root `package.json` contains lint-staged configuration +- **Custom Script**: `scripts/lint-staged-run.sh` filters out generated files that shouldn't be linted +- **File Type Handling**: + - `.{js,ts,cjs,mjs,jsx,tsx}`: ESLint + Prettier + - `.sol`: TODO check + Solhint + Prettier + - `.md`: Markdownlint + Prettier + - `.json`: Prettier only + - `.{yml,yaml}`: YAML lint + Prettier + +**Usage**: `pnpm lint:staged` is particularly useful when you want to check what linting changes will be applied to your staged files before actually committing. + +### TODO Comment Enforcement + +The repository enforces TODO comment resolution to maintain code quality: + +- **Scope**: Applies only to Solidity (`.sol`) files +- **Detection**: Finds TODO, FIXME, XXX, and HACK comments (case-insensitive) +- **Triggers**: + - **Pre-commit**: Blocks commits if TODO comments exist in files being committed + - **Regular linting**: Flags TODO comments in locally changed, staged, or untracked Solidity files +- **Script**: `scripts/check-todos.sh` (must be run from repository root) +- **Bypass**: Use `git commit --no-verify` to bypass (not recommended for production) + +### Key Design Principles + +1. **Hierarchical Configuration**: Root configurations provide base rules, packages can extend as needed +2. **Tool-Specific Inheritance**: ESLint searches up automatically, Prettier requires explicit inheritance +3. **Generated File Exclusion**: Multiple layers of exclusion for autogenerated content +4. **Consistent Formatting**: Prettier ensures consistent code formatting across all file types +5. **Fail-Fast Linting**: Pre-commit hooks catch issues before they enter the repository + +### Configuration Files Reference + +| Tool | Root Config | Package Config | Ignore Files | +| ------------ | --------------------- | -------------------------------- | ---------------------------- | +| ESLint | `eslint.config.mjs` | Auto-inherited | Built into config | +| Prettier | `prettier.config.cjs` | `prettier.config.cjs` (inherits) | `.prettierignore` | +| Solhint | `.solhint.json` | `.solhint.json` (array extends) | N/A | +| NatSpec | No config required | No config required | N/A | +| Markdownlint | `.markdownlint.json` | Auto-inherited | `.markdownlintignore` | +| Lint-staged | `package.json` | N/A | `scripts/lint-staged-run.sh` | + +### Troubleshooting + +- **ESLint not finding config**: ESLint searches up parent directories automatically - no local config needed +- **Prettier not working**: Packages need a `prettier.config.cjs` that inherits from root config +- **Solhint missing rules**: If extending a parent config, use array format: `["solhint:recommended", "./../../.solhint.json"]` to ensure all rules are loaded +- **Solhint inheritance not working**: Nested extends don't work - parent config's `solhint:recommended` won't be inherited with simple string extends +- **Solhint rule reference**: Use `npx solhint list-rules` to see all available rules and their descriptions +- **NatSpec linting failing**: Ensure package dependencies are properly declared in `package.json` and installed. The linting runs in each package's context and resolves imports through the package dependency system +- **Generated files being linted**: Check ignore patterns in `.prettierignore`, `.markdownlintignore`, and ESLint config +- **Preview lint changes before commit**: Use `pnpm lint:staged` to see what changes will be applied to staged files +- **Commit blocked by linting**: Fix the linting issues or use `git commit --no-verify` to bypass (not recommended) + ## Documentation > Coming soon diff --git a/eslint.config.mjs b/eslint.config.mjs index 8b660d4bc..f50113458 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -154,15 +154,6 @@ export default [ }, rules: { 'unused-imports/no-unused-imports': 'warn', - 'unused-imports/no-unused-vars': [ - 'warn', - { - vars: 'all', - varsIgnorePattern: '^_', - args: 'after-used', - argsIgnorePattern: '^_', - }, - ], }, }, @@ -205,8 +196,9 @@ export default [ '@typescript-eslint/no-unused-vars': [ 'error', { - varsIgnorePattern: 'Null|Active|Closed|graph|_i', - argsIgnorePattern: '_', + varsIgnorePattern: '^_|Null|Active|Closed|graph|_i', + argsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', }, ], }, @@ -231,8 +223,8 @@ export default [ 'no-unused-vars': [ 'error', { - varsIgnorePattern: 'Null|Active|Closed|graph|_i', - argsIgnorePattern: '_', + varsIgnorePattern: '^_|Null|Active|Closed|graph|_i', + argsIgnorePattern: '^_', }, ], }, @@ -266,7 +258,11 @@ export default [ // Additional global ignores and unignores { ignores: [ - // Keep any patterns that might not be in .gitignore + // Autogenerated GraphClient files (committed but should not be linted) + '**/.graphclient-extracted/**', + '**/.graphclient/**', + // Third-party dependencies (Forge libraries, etc.) + '**/lib/**', ], }, diff --git a/package.json b/package.json index b2cf7f0ed..3a773164a 100644 --- a/package.json +++ b/package.json @@ -4,33 +4,30 @@ "description": "Contracts monorepo for The Graph protocol", "license": "GPL-2.0-or-later", "repository": "git@github.com:graphprotocol/contracts.git", - "author": "The Graph team", - "packageManager": "pnpm@9.0.6+sha1.648f6014eb363abb36618f2ba59282a9eeb3e879", + "author": "Edge & Node", + "packageManager": "pnpm@10.14.0", "scripts": { "postinstall": "husky", "clean": "pnpm -r run clean", - "clean:all": "pnpm clean && rm -rf node_modules packages/*/node_modules", - "build": "pnpm -r run build", - "lint": "pnpm lint:ts; pnpm lint:sol; pnpm lint:natspec; pnpm lint:md; pnpm lint:json; pnpm lint:yaml", + "clean:all": "pnpm clean && rm -rf node_modules packages/*/node_modules && rm -rf node_modules packages/*/*/node_modules", + "build": "pnpm -r run build:self", + "lint": "pnpm lint:ts; pnpm lint:sol; pnpm lint:md; pnpm lint:json; pnpm lint:yaml", + "lint:staged": "npx lint-staged", "lint:ts": "eslint --fix --cache '**/*.{js,ts,cjs,mjs,jsx,tsx}'; prettier -w --cache --log-level warn '**/*.{js,ts,cjs,mjs,jsx,tsx}'", - "lint:sol": "solhint --fix --noPrompt --noPoster 'packages/*/contracts/**/*.sol'; prettier -w --cache --log-level warn '**/*.sol'", - "lint:natspec": "node scripts/filter-natspec.js", - "lint:md": "markdownlint --fix --ignore-path .gitignore '**/*.md'; prettier -w --cache --log-level warn '**/*.md'", + "lint:sol": "scripts/check-todos.sh; pnpm -r run lint:sol", + "lint:md": "markdownlint --fix --ignore-path .gitignore --ignore-path .markdownlintignore '**/*.md'; prettier -w --cache --log-level warn '**/*.md'", "lint:json": "prettier -w --cache --log-level warn '**/*.json'", "lint:yaml": "npx yaml-lint .github/**/*.{yml,yaml} packages/contracts/task/config/*.yml; prettier -w --cache --log-level warn '**/*.{yml,yaml}'", "format": "prettier -w --cache --log-level warn '**/*.{js,ts,cjs,mjs,jsx,tsx,json,md,yaml,yml}'", - "test": "pnpm -r run test", + "test": "pnpm -r run test:self", "test:coverage": "pnpm -r run test:coverage" }, "devDependencies": { "@changesets/cli": "^2.27.1", "@commitlint/cli": "19.8.1", "@commitlint/config-conventional": "19.8.1", - "@defi-wonderland/natspec-smells": "^1.1.6", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "^9.28.0", - "@openzeppelin/contracts": "^5.3.0", - "@openzeppelin/contracts-upgradeable": "^5.3.0", "@typescript-eslint/eslint-plugin": "^8.33.1", "@typescript-eslint/parser": "^8.33.1", "eslint": "^9.28.0", @@ -48,7 +45,7 @@ "prettier": "^3.5.3", "prettier-plugin-solidity": "^1.0.0", "pretty-quick": "^4.1.1", - "solhint": "^5.1.0", + "solhint": "catalog:", "typescript": "^5.8.3", "typescript-eslint": "^8.33.1", "yaml-lint": "^1.7.0" @@ -66,10 +63,11 @@ }, "lint-staged": { "*.{js,ts,cjs,mjs,jsx,tsx}": [ - "eslint --fix --cache", - "prettier -w --cache --log-level warn" + "scripts/lint-staged-run.sh 'eslint --fix --cache'", + "scripts/lint-staged-run.sh 'prettier -w --cache --log-level warn'" ], "*.sol": [ + "scripts/check-todos.sh", "solhint --fix --noPrompt --noPoster", "prettier -w --cache --log-level warn" ], diff --git a/packages/common/.solhint.json b/packages/common/.solhint.json new file mode 100644 index 000000000..d30847305 --- /dev/null +++ b/packages/common/.solhint.json @@ -0,0 +1,3 @@ +{ + "extends": ["solhint:recommended", "./../../.solhint.json"] +} diff --git a/packages/common/contracts/rewards/IRewardsManager.sol b/packages/common/contracts/rewards/IRewardsManager.sol index 4bd42cad0..5d750dd85 100644 --- a/packages/common/contracts/rewards/IRewardsManager.sol +++ b/packages/common/contracts/rewards/IRewardsManager.sol @@ -2,9 +2,14 @@ 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 @@ -58,13 +63,7 @@ interface IRewardsManager { /** * @notice Gets the issuance of rewards per signal since last updated - * @dev Linear formula: `x = r * t` - * - * Notation: - * t: time steps are in blocks since last updated - * x: newly accrued rewards tokens for the period `t` - * - * @return newly accrued rewards per signal since last update, scaled by FIXED_POINT_SCALING_FACTOR + * @return newly accrued rewards per signal since last update */ function getNewRewardsPerSignal() external view returns (uint256); diff --git a/packages/common/contracts/token/IGraphToken.sol b/packages/common/contracts/token/IGraphToken.sol index c1d44a2f3..924183e46 100644 --- a/packages/common/contracts/token/IGraphToken.sol +++ b/packages/common/contracts/token/IGraphToken.sol @@ -2,10 +2,13 @@ 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 */ diff --git a/packages/common/package.json b/packages/common/package.json index cf0842774..8072a6d5f 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -21,32 +21,27 @@ "license": "GPL-2.0-or-later", "scripts": { "clean": "rm -rf build cache types artifacts", - "lint": "pnpm lint:ts; pnpm lint:sol; pnpm lint:natspec; pnpm lint:md; pnpm lint:json", + "lint": "pnpm lint:ts; pnpm lint:sol; pnpm lint:md; pnpm lint:json", "lint:ts": "eslint '**/*.{js,ts,cjs,mjs,jsx,tsx}' --fix --cache; prettier -w --cache --log-level warn '**/*.{js,ts,cjs,mjs,jsx,tsx}'", "lint:sol": "solhint --fix --noPrompt --noPoster 'contracts/**/*.sol'; prettier -w --cache --log-level warn 'contracts/**/*.sol'", - "lint:natspec": "cd ../.. && node scripts/filter-natspec.js --include 'packages/common/contracts/**/*.sol'", "lint:md": "markdownlint --fix --ignore-path ../../.gitignore '**/*.md'; prettier -w --cache --log-level warn '**/*.md'", "lint:json": "prettier -w --cache --log-level warn '**/*.json'", - "format": "prettier -w --cache --log-level warn '**/*.{js,ts,cjs,mjs,jsx,tsx,json,md,yaml,yml}'", - "build": "hardhat compile", - "build:contracts": "hardhat compile", - "build:clean": "pnpm clean && pnpm build" + "format": "prettier -w --cache --log-level warn '**/*.{js,ts,cjs,mjs,jsx,tsx,json,md,yaml,yml}'" }, "dependencies": { "dotenv": "^16.3.1" }, "devDependencies": { - "@defi-wonderland/natspec-smells": "^1.1.6", + "@openzeppelin/contracts": "^5.3.0", + "@openzeppelin/contracts-upgradeable": "^5.3.0", "@types/node": "^20.17.50", - "eslint": "^9.28.0", - "eslint-config-prettier": "^10.1.5", + "eslint": "catalog:", + "eslint-config-prettier": "catalog:", "globals": "^16.1.0", - "hardhat": "^2.24.0", - "markdownlint-cli": "^0.45.0", - "prettier": "^3.5.3", - "prettier-plugin-solidity": "^2.0.0", - "solhint": "5.1.0", - "typescript": "^5.8.3", - "typescript-eslint": "^8.33.1" + "markdownlint-cli": "catalog:", + "prettier": "catalog:", + "solhint": "catalog:", + "typescript": "catalog:", + "typescript-eslint": "catalog:" } } diff --git a/packages/contracts/.solhint.json b/packages/contracts/.solhint.json new file mode 100644 index 000000000..d30847305 --- /dev/null +++ b/packages/contracts/.solhint.json @@ -0,0 +1,3 @@ +{ + "extends": ["solhint:recommended", "./../../.solhint.json"] +} 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 index d7d5a2d8c..6517f0c57 100644 --- a/packages/contracts/contracts/arbitrum/IArbToken.sol +++ b/packages/contracts/contracts/arbitrum/IArbToken.sol @@ -29,18 +29,28 @@ */ pragma solidity ^0.7.6; +/** + * @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/contracts/contracts/arbitrum/IBridge.sol b/packages/contracts/contracts/arbitrum/IBridge.sol index 536ee075b..92deee878 100644 --- a/packages/contracts/contracts/arbitrum/IBridge.sol +++ b/packages/contracts/contracts/arbitrum/IBridge.sol @@ -25,7 +25,24 @@ pragma solidity ^0.7.6; +// 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/contracts/contracts/arbitrum/IInbox.sol b/packages/contracts/contracts/arbitrum/IInbox.sol index a9315bbf8..8ded1c1bb 100644 --- a/packages/contracts/contracts/arbitrum/IInbox.sol +++ b/packages/contracts/contracts/arbitrum/IInbox.sol @@ -25,12 +25,32 @@ pragma solidity ^0.7.6; -import "./IBridge.sol"; -import "./IMessageProvider.sol"; +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/contracts/contracts/arbitrum/IMessageProvider.sol b/packages/contracts/contracts/arbitrum/IMessageProvider.sol index 8fbfdb171..ce5822358 100644 --- a/packages/contracts/contracts/arbitrum/IMessageProvider.sol +++ b/packages/contracts/contracts/arbitrum/IMessageProvider.sol @@ -25,8 +25,22 @@ pragma solidity ^0.7.6; +/** + * @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/contracts/contracts/arbitrum/IOutbox.sol b/packages/contracts/contracts/arbitrum/IOutbox.sol index 2e4f05bd5..658a6c233 100644 --- a/packages/contracts/contracts/arbitrum/IOutbox.sol +++ b/packages/contracts/contracts/arbitrum/IOutbox.sol @@ -25,13 +25,36 @@ pragma solidity ^0.7.6; +// 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/contracts/contracts/arbitrum/ITokenGateway.sol b/packages/contracts/contracts/arbitrum/ITokenGateway.sol index 977fe07f2..fd0094398 100644 --- a/packages/contracts/contracts/arbitrum/ITokenGateway.sol +++ b/packages/contracts/contracts/arbitrum/ITokenGateway.sol @@ -25,6 +25,11 @@ pragma solidity ^0.7.6; +/** + * @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,21 +51,39 @@ 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 _amount, - uint256 _maxGas, - uint256 _gasPriceBid, - bytes calldata _data + address token, + address to, + 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, - address _to, - uint256 _amount, - bytes calldata _data + address token, + address from, + address to, + uint256 amount, + bytes calldata data ) external payable; /** diff --git a/packages/contracts/contracts/arbitrum/L1ArbitrumMessenger.sol b/packages/contracts/contracts/arbitrum/L1ArbitrumMessenger.sol index 839e1930b..9613294ad 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 "./IInbox.sol"; +import { IOutbox } from "./IOutbox.sol"; +import { IBridge } from "./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 index 3269f694b..9b9de5ad0 100644 --- a/packages/contracts/contracts/base/IMulticall.sol +++ b/packages/contracts/contracts/base/IMulticall.sol @@ -5,6 +5,7 @@ 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/contracts/contracts/base/Multicall.sol b/packages/contracts/contracts/base/Multicall.sol index 49111840d..9d9d48d34 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 "./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 173f1603a..4153d2c02 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"; @@ -18,7 +21,8 @@ import { IGraphCurationToken } from "./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 @@ -256,7 +268,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { /** * @notice Get the amount of token reserves in a curation pool. - * @param _subgraphDeploymentID Subgraph deployment curation poool + * @param _subgraphDeploymentID Subgraph deployment curation pool * @return Amount of token reserves in the curation pool */ function getCurationPoolTokens(bytes32 _subgraphDeploymentID) external view override returns (uint256) { @@ -285,7 +297,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { /** * @notice Get the amount of signal in a curation pool. - * @param _subgraphDeploymentID Subgraph deployment curation poool + * @param _subgraphDeploymentID Subgraph deployment curation pool * @return Amount of signal minted for the subgraph deployment */ function getCurationPoolSignal(bytes32 _subgraphDeploymentID) public view override returns (uint256) { @@ -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 bcbf0df6b..8a22f0568 100644 --- a/packages/contracts/contracts/curation/CurationStorage.sol +++ b/packages/contracts/contracts/curation/CurationStorage.sol @@ -1,7 +1,11 @@ // 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 + import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol"; import { ICuration } from "./ICuration.sol"; @@ -10,7 +14,8 @@ 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. 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 index d92aa9c69..64cc97948 100644 --- a/packages/contracts/contracts/curation/ICuration.sol +++ b/packages/contracts/contracts/curation/ICuration.sol @@ -4,7 +4,8 @@ pragma solidity ^0.7.6; /** * @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 -- @@ -84,14 +85,14 @@ interface ICuration { /** * @notice Get the amount of signal in a curation pool. - * @param _subgraphDeploymentID Subgraph deployment curation poool + * @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 poool + * @param _subgraphDeploymentID Subgraph deployment curation pool * @return Amount of token reserves in the curation pool */ function getCurationPoolTokens(bytes32 _subgraphDeploymentID) external view returns (uint256); diff --git a/packages/contracts/contracts/curation/IGraphCurationToken.sol b/packages/contracts/contracts/curation/IGraphCurationToken.sol index 43679aba6..10dda6dcf 100644 --- a/packages/contracts/contracts/curation/IGraphCurationToken.sol +++ b/packages/contracts/contracts/curation/IGraphCurationToken.sol @@ -2,12 +2,31 @@ pragma solidity ^0.7.6; -import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; +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/contracts/contracts/discovery/GNS.sol b/packages/contracts/contracts/discovery/GNS.sol index 3cbb9ca8a..27310242c 100644 --- a/packages/contracts/contracts/discovery/GNS.sol +++ b/packages/contracts/contracts/discovery/GNS.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 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"; @@ -18,7 +21,8 @@ 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..f9cddf2c6 100644 --- a/packages/contracts/contracts/discovery/GNSStorage.sol +++ b/packages/contracts/contracts/discovery/GNSStorage.sol @@ -1,8 +1,12 @@ // 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 one-contract-per-file + import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol"; import { Managed } from "../governance/Managed.sol"; @@ -12,12 +16,13 @@ import { ISubgraphNFT } from "./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 index 9267c70d2..e962348c7 100644 --- a/packages/contracts/contracts/discovery/IGNS.sol +++ b/packages/contracts/contracts/discovery/IGNS.sol @@ -4,6 +4,8 @@ pragma solidity ^0.7.6; /** * @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,6 +35,8 @@ 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; @@ -158,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); @@ -167,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/contracts/contracts/discovery/IServiceRegistry.sol b/packages/contracts/contracts/discovery/IServiceRegistry.sol index da284a409..94c7e428e 100644 --- a/packages/contracts/contracts/discovery/IServiceRegistry.sol +++ b/packages/contracts/contracts/discovery/IServiceRegistry.sol @@ -2,19 +2,52 @@ pragma solidity ^0.7.6; +/** + * @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/contracts/contracts/discovery/ISubgraphNFT.sol b/packages/contracts/contracts/discovery/ISubgraphNFT.sol index 4b0495a28..9d6fe87a0 100644 --- a/packages/contracts/contracts/discovery/ISubgraphNFT.sol +++ b/packages/contracts/contracts/discovery/ISubgraphNFT.sol @@ -2,24 +2,66 @@ pragma solidity ^0.7.6; -import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +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/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol b/packages/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol index cd0785dcb..5a6893234 100644 --- a/packages/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol +++ b/packages/contracts/contracts/discovery/ISubgraphNFTDescriptor.sol @@ -2,7 +2,11 @@ pragma solidity ^0.7.6; -/// @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/contracts/contracts/discovery/L1GNS.sol b/packages/contracts/contracts/discovery/L1GNS.sol index 55a831259..adbb51831 100644 --- a/packages/contracts/contracts/discovery/L1GNS.sol +++ b/packages/contracts/contracts/discovery/L1GNS.sol @@ -14,7 +14,8 @@ 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..c5726a0ca 100644 --- a/packages/contracts/contracts/discovery/L1GNSStorage.sol +++ b/packages/contracts/contracts/discovery/L1GNSStorage.sol @@ -5,12 +5,13 @@ 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..3fa27f452 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 "./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..7d4613d7d 100644 --- a/packages/contracts/contracts/discovery/ServiceRegistryStorage.sol +++ b/packages/contracts/contracts/discovery/ServiceRegistryStorage.sol @@ -2,12 +2,18 @@ pragma solidity ^0.7.6; -import "../governance/Managed.sol"; +import { Managed } from "../governance/Managed.sol"; -import "./IServiceRegistry.sol"; +import { IServiceRegistry } from "./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..a423a70a4 100644 --- a/packages/contracts/contracts/discovery/SubgraphNFT.sol +++ b/packages/contracts/contracts/discovery/SubgraphNFT.sol @@ -2,35 +2,65 @@ 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 + +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 "./ISubgraphNFT.sol"; +import { ISubgraphNFTDescriptor } from "./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 +68,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 +85,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 +105,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 +114,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..a21cadfb7 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 "./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..1cb3602ed 100644 --- a/packages/contracts/contracts/discovery/erc1056/EthereumDIDRegistry.sol +++ b/packages/contracts/contracts/discovery/erc1056/EthereumDIDRegistry.sol @@ -12,19 +12,50 @@ 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 + +/** + * @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 +64,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 +80,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 +93,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 +115,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 +172,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 +200,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 +246,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 +266,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 +308,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 +328,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 +374,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 +391,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 index 8de69f304..0be104968 100644 --- a/packages/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol +++ b/packages/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol @@ -2,8 +2,25 @@ pragma solidity ^0.7.6; +/** + * @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/contracts/contracts/disputes/DisputeManager.sol b/packages/contracts/contracts/disputes/DisputeManager.sol index 6700ec341..b07d7933c 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 "../staking/IStaking.sol"; -/* +import { DisputeManagerV1Storage } from "./DisputeManagerStorage.sol"; +import { IDisputeManager } from "./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) @@ -179,7 +233,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa _setSlashingPercentage(_qrySlashingPercentage, _idxSlashingPercentage); // EIP-712 domain separator - DOMAIN_SEPARATOR = keccak256( + domainSeparator = keccak256( abi.encode( DOMAIN_TYPE_HASH, DOMAIN_NAME_HASH, @@ -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,28 +322,23 @@ 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 keccak256( abi.encodePacked( "\x19\x01", // EIP-191 encoding pad, EIP-712 version 1 - DOMAIN_SEPARATOR, + domainSeparator, keccak256( abi.encode( RECEIPT_TYPE_HASH, @@ -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,19 +505,19 @@ 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, address _allocationID - ) private returns (bytes32) { + ) private returns (bytes32 disputeID) { // Create a disputeID - bytes32 disputeID = keccak256(abi.encodePacked(_allocationID)); + disputeID = keccak256(abi.encodePacked(_allocationID)); // Only one dispute for an allocationID at a time require(!isDisputeCreated(disputeID), "Dispute already created"); @@ -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) public 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..8d54eb74a 100644 --- a/packages/contracts/contracts/disputes/DisputeManagerStorage.sol +++ b/packages/contracts/contracts/disputes/DisputeManagerStorage.sol @@ -2,33 +2,40 @@ pragma solidity ^0.7.6; -import "../governance/Managed.sol"; +import { Managed } from "../governance/Managed.sol"; -import "./IDisputeManager.sol"; +import { IDisputeManager } from "./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 domainSeparator; - // 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 index 8c6668371..2064fc5e7 100644 --- a/packages/contracts/contracts/disputes/IDisputeManager.sol +++ b/packages/contracts/contracts/disputes/IDisputeManager.sol @@ -3,15 +3,26 @@ pragma solidity ^0.7.6; 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/contracts/contracts/epochs/EpochManager.sol b/packages/contracts/contracts/epochs/EpochManager.sol index 281b63896..440f3d1cb 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 "./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 index 36b1f47a3..c59139249 100644 --- a/packages/contracts/contracts/epochs/IEpochManager.sol +++ b/packages/contracts/contracts/epochs/IEpochManager.sol @@ -2,30 +2,77 @@ pragma solidity ^0.7.6; +/** + * @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); + /** + * @notice Get the hash of a specific block + * @param _block Block number to get hash for + * @return Block hash + */ function blockHash(uint256 _block) 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/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..f11f52f7d 100644 --- a/packages/contracts/contracts/gateway/GraphTokenGateway.sol +++ b/packages/contracts/contracts/gateway/GraphTokenGateway.sol @@ -9,7 +9,8 @@ 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 index 885b0cdb2..a37a42380 100644 --- a/packages/contracts/contracts/gateway/ICallhookReceiver.sol +++ b/packages/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; +/** + * @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/contracts/contracts/gateway/L1GraphTokenGateway.sol b/packages/contracts/contracts/gateway/L1GraphTokenGateway.sol index 73e414866..3bd0c6f0e 100644 --- a/packages/contracts/contracts/gateway/L1GraphTokenGateway.sol +++ b/packages/contracts/contracts/gateway/L1GraphTokenGateway.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-strict-inequalities + 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"; @@ -18,7 +21,8 @@ import { IGraphToken } from "@graphprotocol/common/contracts/token/IGraphToken.s /** * @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 +32,35 @@ import { IGraphToken } from "@graphprotocol/common/contracts/token/IGraphToken.s 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 +69,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 +85,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 +250,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 +272,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 +297,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 +305,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 +345,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 +371,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 +421,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 +457,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 +470,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 +486,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 affb29a05..0e582df44 100644 --- a/packages/contracts/contracts/governance/Controller.sol +++ b/packages/contracts/contracts/governance/Controller.sol @@ -2,6 +2,11 @@ pragma solidity ^0.7.6; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events, gas-small-strings + +/* solhint-disable gas-custom-errors */ // Cannot use custom errors with 0.7.6 + import { IController } from "./IController.sol"; import { IManaged } from "./IManaged.sol"; import { Governed } from "./Governed.sol"; @@ -9,14 +14,19 @@ 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 +47,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 +56,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 +65,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 +73,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"); @@ -87,26 +90,23 @@ contract Controller is Governed, Pausable, IController { // -- Pausing -- /** - * @notice Change the partial paused state of the contract - * Partial pause is intended as a partial pause of the protocol - * @param _toPause True if the contracts should be (partially) paused, false otherwise + * @inheritdoc IController + * @dev Partial pause is intended as a partial pause of the protocol */ function setPartialPaused(bool _toPause) external override onlyGovernorOrGuardian { _setPartialPaused(_toPause); } /** - * @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 +114,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 f692b2d19..44fc5498d 100644 --- a/packages/contracts/contracts/governance/Governed.sol +++ b/packages/contracts/contracts/governance/Governed.sol @@ -2,23 +2,39 @@ pragma solidity ^0.7.6; +/* 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 index 7df3d94ee..09f03dbb1 100644 --- a/packages/contracts/contracts/governance/IController.sol +++ b/packages/contracts/contracts/governance/IController.sol @@ -2,28 +2,78 @@ pragma solidity >=0.6.12 <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 -- + /** + * @notice Change the partial paused state of the contract + * Partial pause is intended as a partial pause of the protocol + * @param _partialPaused True if the contracts should be (partially) paused, false otherwise + */ function setPartialPaused(bool _partialPaused) external; + /** + * @notice Change the paused state of the contract + * Full pause most of protocol functions + * @param _paused True if the contracts should be paused, false otherwise + */ function setPaused(bool _paused) 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/contracts/contracts/governance/IManaged.sol b/packages/contracts/contracts/governance/IManaged.sol index 76f05e0fb..988146318 100644 --- a/packages/contracts/contracts/governance/IManaged.sol +++ b/packages/contracts/contracts/governance/IManaged.sol @@ -6,21 +6,21 @@ 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 + * @notice Set Controller. Only callable by current controller. + * @param _controller Controller contract address */ 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. + * @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. + * controller to ensure the protocol is using the latest version */ function syncAllContracts() external; diff --git a/packages/contracts/contracts/governance/Managed.sol b/packages/contracts/contracts/governance/Managed.sol index f542f3d2c..890c4366a 100644 --- a/packages/contracts/contracts/governance/Managed.sol +++ b/packages/contracts/contracts/governance/Managed.sol @@ -2,6 +2,9 @@ pragma solidity ^0.7.6; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-indexed-events + import { IController } from "./IController.sol"; import { ICuration } from "../curation/ICuration.sol"; @@ -16,7 +19,8 @@ import { IManaged } from "./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 +30,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 +40,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 +87,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 +142,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 +150,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 +167,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 +175,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 +183,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 +191,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 +199,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 +207,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 +215,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 +223,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 +236,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 +248,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 552b0aa15..a4b130008 100644 --- a/packages/contracts/contracts/governance/Pausable.sol +++ b/packages/contracts/contracts/governance/Pausable.sol @@ -2,6 +2,14 @@ pragma solidity ^0.7.6; +// 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 lastPausePartialTime; - /// 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 _toPause New value for the partial pause state (true means the contracts will be partially paused) */ function _setPartialPaused(bool _toPause) 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 index bbbfd82ff..c1320c762 100644 --- a/packages/contracts/contracts/l2/curation/IL2Curation.sol +++ b/packages/contracts/contracts/l2/curation/IL2Curation.sol @@ -4,6 +4,8 @@ pragma solidity ^0.7.6; /** * @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/contracts/contracts/l2/curation/L2Curation.sol b/packages/contracts/contracts/l2/curation/L2Curation.sol index 1d736b9fb..2e58b3cf2 100644 --- a/packages/contracts/contracts/l2/curation/L2Curation.sol +++ b/packages/contracts/contracts/l2/curation/L2Curation.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"; @@ -18,7 +21,8 @@ import { IL2Curation } from "./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 CurationV2Storage, 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,14 +66,20 @@ contract L2Curation is CurationV2Storage, 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); @@ -102,7 +118,8 @@ contract L2Curation is CurationV2Storage, 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"); } @@ -157,7 +174,8 @@ contract L2Curation is CurationV2Storage, 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, @@ -211,12 +229,7 @@ contract L2Curation is CurationV2Storage, 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, @@ -312,7 +325,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { /** * @notice Get the amount of token reserves in a curation pool. - * @param _subgraphDeploymentID Subgraph deployment curation poool + * @param _subgraphDeploymentID Subgraph deployment curation pool * @return Amount of token reserves in the curation pool */ function getCurationPoolTokens(bytes32 _subgraphDeploymentID) external view override returns (uint256) { @@ -341,7 +354,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { /** * @notice Get the amount of signal in a curation pool. - * @param _subgraphDeploymentID Subgraph deployment curation poool + * @param _subgraphDeploymentID Subgraph deployment curation pool * @return Amount of signal minted for the subgraph deployment */ function getCurationPoolSignal(bytes32 _subgraphDeploymentID) public view override returns (uint256) { @@ -370,11 +383,7 @@ contract L2Curation is CurationV2Storage, 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, @@ -384,12 +393,7 @@ contract L2Curation is CurationV2Storage, 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, @@ -419,7 +423,7 @@ contract L2Curation is CurationV2Storage, 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 */ @@ -431,7 +435,7 @@ contract L2Curation is CurationV2Storage, 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 { @@ -442,7 +446,7 @@ contract L2Curation is CurationV2Storage, 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 { @@ -454,7 +458,7 @@ contract L2Curation is CurationV2Storage, 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 { @@ -465,7 +469,7 @@ contract L2Curation is CurationV2Storage, 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 index 4864e9bc1..80a539c83 100644 --- a/packages/contracts/contracts/l2/discovery/IL2GNS.sol +++ b/packages/contracts/contracts/l2/discovery/IL2GNS.sol @@ -6,8 +6,15 @@ 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/contracts/contracts/l2/discovery/L2GNS.sol b/packages/contracts/contracts/l2/discovery/L2GNS.sol index 34d47d400..cf5528953 100644 --- a/packages/contracts/contracts/l2/discovery/L2GNS.sol +++ b/packages/contracts/contracts/l2/discovery/L2GNS.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 { SafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import { GNS } from "../../discovery/GNS.sol"; @@ -14,7 +17,8 @@ import { IL2Curation } from "../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..36aa0657f 100644 --- a/packages/contracts/contracts/l2/discovery/L2GNSStorage.sol +++ b/packages/contracts/contracts/l2/discovery/L2GNSStorage.sol @@ -7,11 +7,11 @@ import { IL2GNS } from "./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..3b4c1c0ed 100644 --- a/packages/contracts/contracts/l2/gateway/L2GraphTokenGateway.sol +++ b/packages/contracts/contracts/l2/gateway/L2GraphTokenGateway.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 + import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { SafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; @@ -16,7 +19,8 @@ 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 index 73ff936ce..90d1507e0 100644 --- a/packages/contracts/contracts/l2/staking/IL2Staking.sol +++ b/packages/contracts/contracts/l2/staking/IL2Staking.sol @@ -8,6 +8,7 @@ import { IL2StakingBase } from "./IL2StakingBase.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. @@ -22,12 +23,19 @@ interface IL2Staking is IStaking, IL2StakingBase { RECEIVE_DELEGATION_CODE } - /// @dev Encoded message struct when receiving indexer stake through the bridge + /** + * @dev Encoded message struct when receiving indexer stake through the bridge + * @param indexer Address of the indexer + */ struct ReceiveIndexerStakeData { address indexer; } - /// @dev Encoded message struct when receiving delegation through the bridge + /** + * @dev Encoded message struct when receiving delegation through the bridge + * @param indexer Address of the indexer + * @param delegator Address of the delegator + */ struct ReceiveDelegationData { address indexer; address delegator; diff --git a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol index 6f701ec89..5990db514 100644 --- a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol +++ b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol @@ -2,13 +2,23 @@ pragma solidity ^0.7.6; +// 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/contracts/contracts/l2/staking/L2Staking.sol b/packages/contracts/contracts/l2/staking/L2Staking.sol index 3f9d28e5a..ea2263ae3 100644 --- a/packages/contracts/contracts/l2/staking/L2Staking.sol +++ b/packages/contracts/contracts/l2/staking/L2Staking.sol @@ -3,15 +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 + import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; import { Staking } from "../../staking/Staking.sol"; import { IL2StakingBase } from "./IL2StakingBase.sol"; import { IL2Staking } from "./IL2Staking.sol"; import { Stakes } from "../../staking/libs/Stakes.sol"; +// solhint-disable-next-line no-unused-import +import { ICallhookReceiver } from "../../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. */ @@ -23,10 +30,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); @@ -47,7 +58,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. @@ -81,7 +92,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 @@ -101,7 +112,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..d7dcb3520 100644 --- a/packages/contracts/contracts/l2/token/GraphTokenUpgradeable.sol +++ b/packages/contracts/contracts/l2/token/GraphTokenUpgradeable.sol @@ -2,6 +2,9 @@ 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 + import { ERC20BurnableUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol"; import { ECDSAUpgradeable } from "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol"; @@ -10,7 +13,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 +51,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 +156,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 +184,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 +193,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 +202,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..c16f0164c 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"; /** * @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 b40e57e25..200eb4f2b 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 -import "../governance/Governed.sol"; -import "../staking/IStaking.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 "../staking/IStaking.sol"; import { IGraphToken } from "@graphprotocol/common/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 "@graphprotocol/common/contracts/token/IGraphToken.s * 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/RewardsManager.sol b/packages/contracts/contracts/rewards/RewardsManager.sol index 586a30e8c..d24f06243 100644 --- a/packages/contracts/contracts/rewards/RewardsManager.sol +++ b/packages/contracts/contracts/rewards/RewardsManager.sol @@ -3,11 +3,14 @@ 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 { Managed } from "../governance/Managed.sol"; import { IGraphToken } from "@graphprotocol/common/contracts/token/IGraphToken.sol"; import { IStaking, IStakingBase } from "../staking/IStaking.sol"; @@ -16,6 +19,8 @@ import { IRewardsManager } from "@graphprotocol/common/contracts/rewards/IReward /** * @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 { IRewardsManager } from "@graphprotocol/common/contracts/rewards/IReward * - 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 RewardsManagerV4Storage, GraphUpgradeable, IRewardsManager { using SafeMath for uint256; @@ -40,7 +46,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa // -- Events -- /** - * @dev Emitted when rewards are assigned to an indexer + * @notice Emitted when rewards are assigned to an indexer * @param indexer Address of the indexer receiving rewards * @param allocationID Address of the allocation receiving rewards * @param epoch Epoch when the rewards were assigned @@ -49,7 +55,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa event RewardsAssigned(address indexed indexer, address indexed allocationID, uint256 epoch, 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 * @param epoch Epoch when the rewards were denied @@ -57,7 +63,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa event RewardsDenied(address indexed indexer, address indexed allocationID, uint256 epoch); /** - * @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 */ @@ -84,20 +90,19 @@ contract RewardsManager is RewardsManagerV4Storage, 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 { @@ -109,8 +114,7 @@ contract RewardsManager is RewardsManagerV4Storage, 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; @@ -118,9 +122,8 @@ contract RewardsManager is RewardsManagerV4Storage, 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 */ function setMinimumSubgraphSignal(uint256 _minimumSubgraphSignal) external override { // Caller can be the SAO or the governor @@ -135,17 +138,15 @@ contract RewardsManager is RewardsManagerV4Storage, 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 */ @@ -155,11 +156,7 @@ contract RewardsManager is RewardsManagerV4Storage, 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; } @@ -167,7 +164,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa // -- Getters -- /** - * @notice Gets the issuance of rewards per signal since last updated + * @inheritdoc IRewardsManager * @dev Linear formula: `x = r * t` * * Notation: @@ -202,19 +199,12 @@ contract RewardsManager is RewardsManagerV4Storage, 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]; @@ -230,12 +220,7 @@ contract RewardsManager is RewardsManagerV4Storage, 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) { @@ -261,10 +246,9 @@ contract RewardsManager is RewardsManagerV4Storage, 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(); @@ -273,11 +257,9 @@ contract RewardsManager is RewardsManagerV4Storage, 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 @@ -291,12 +273,8 @@ contract RewardsManager is RewardsManagerV4Storage, 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]; @@ -308,11 +286,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa return subgraph.accRewardsPerAllocatedToken; } - /** - * @notice Calculate current rewards for a given allocation on demand - * @param _allocationID Allocation - * @return Rewards amount for an allocation - */ + /// @inheritdoc IRewardsManager function getRewards(address _allocationID) external view override returns (uint256) { IStaking.AllocationState allocState = staking().getAllocationState(_allocationID); if (allocState != IStakingBase.AllocationState.Active) { @@ -326,7 +300,7 @@ contract RewardsManager is RewardsManagerV4Storage, 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 @@ -342,11 +316,9 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa } /** - * @notice Pull rewards from the contract for a particular allocation + * @inheritdoc IRewardsManager * @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 override returns (uint256) { // Only Staking contract is authorized as caller diff --git a/packages/contracts/contracts/rewards/RewardsManagerStorage.sol b/packages/contracts/contracts/rewards/RewardsManagerStorage.sol index 5092589d3..1901b531e 100644 --- a/packages/contracts/contracts/rewards/RewardsManagerStorage.sol +++ b/packages/contracts/contracts/rewards/RewardsManagerStorage.sol @@ -7,34 +7,58 @@ pragma solidity 0.7.6; import { IRewardsManager } from "@graphprotocol/common/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; } diff --git a/packages/contracts/contracts/rewards/SubgraphAvailabilityManager.sol b/packages/contracts/contracts/rewards/SubgraphAvailabilityManager.sol index e9aec584d..824113482 100644 --- a/packages/contracts/contracts/rewards/SubgraphAvailabilityManager.sol +++ b/packages/contracts/contracts/rewards/SubgraphAvailabilityManager.sol @@ -2,12 +2,16 @@ 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 + import { Governed } from "../governance/Governed.sol"; import { IRewardsManager } from "@graphprotocol/common/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 +25,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 +44,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 +77,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 +90,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 +127,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 +137,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 +153,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 +164,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 +182,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 +212,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 index b935682b9..9a2224048 100644 --- a/packages/contracts/contracts/staking/IL1GraphTokenLockTransferTool.sol +++ b/packages/contracts/contracts/staking/IL1GraphTokenLockTransferTool.sol @@ -5,7 +5,8 @@ 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/contracts/contracts/staking/IL1Staking.sol b/packages/contracts/contracts/staking/IL1Staking.sol index 4a446f787..d64372f0a 100644 --- a/packages/contracts/contracts/staking/IL1Staking.sol +++ b/packages/contracts/contracts/staking/IL1Staking.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/contracts/contracts/staking/IL1StakingBase.sol b/packages/contracts/contracts/staking/IL1StakingBase.sol index fad2136c2..09b2c3cca 100644 --- a/packages/contracts/contracts/staking/IL1StakingBase.sol +++ b/packages/contracts/contracts/staking/IL1StakingBase.sol @@ -3,23 +3,39 @@ pragma solidity >=0.6.12 <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/contracts/contracts/staking/IStaking.sol b/packages/contracts/contracts/staking/IStaking.sol index aad1eab1b..83b7f9cc1 100644 --- a/packages/contracts/contracts/staking/IStaking.sol +++ b/packages/contracts/contracts/staking/IStaking.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/contracts/contracts/staking/IStakingBase.sol b/packages/contracts/contracts/staking/IStakingBase.sol index b30d00499..3c8ec7c0e 100644 --- a/packages/contracts/contracts/staking/IStakingBase.sol +++ b/packages/contracts/contracts/staking/IStakingBase.sol @@ -3,10 +3,15 @@ pragma solidity >=0.6.12 <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. diff --git a/packages/contracts/contracts/staking/IStakingData.sol b/packages/contracts/contracts/staking/IStakingData.sol index 5420c66e5..031abd3dc 100644 --- a/packages/contracts/contracts/staking/IStakingData.sol +++ b/packages/contracts/contracts/staking/IStakingData.sol @@ -4,12 +4,22 @@ pragma solidity >=0.6.12 <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/contracts/contracts/staking/IStakingExtension.sol b/packages/contracts/contracts/staking/IStakingExtension.sol index 6a60dc9eb..5a3cb48ad 100644 --- a/packages/contracts/contracts/staking/IStakingExtension.sol +++ b/packages/contracts/contracts/staking/IStakingExtension.sol @@ -3,12 +3,16 @@ pragma solidity >=0.6.12 <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 { Stakes } from "./libs/Stakes.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); @@ -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/contracts/contracts/staking/L1Staking.sol b/packages/contracts/contracts/staking/L1Staking.sol index 1c9f1e0a0..c3c235022 100644 --- a/packages/contracts/contracts/staking/L1Staking.sol +++ b/packages/contracts/contracts/staking/L1Staking.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 function-max-lines, gas-strict-inequalities + import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; import { ITokenGateway } from "../arbitrum/ITokenGateway.sol"; @@ -18,7 +21,8 @@ import { IL1GraphTokenLockTransferTool } from "./IL1GraphTokenLockTransferTool.s /** * @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 { @@ -35,9 +39,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 @@ -47,21 +49,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, @@ -75,22 +63,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, @@ -108,20 +81,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, @@ -143,21 +103,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, @@ -183,13 +129,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( @@ -208,13 +148,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 @@ -281,12 +222,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 @@ -348,7 +290,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..9073acc90 100644 --- a/packages/contracts/contracts/staking/L1StakingStorage.sol +++ b/packages/contracts/contracts/staking/L1StakingStorage.sol @@ -7,12 +7,13 @@ import { IL1GraphTokenLockTransferTool } from "./IL1GraphTokenLockTransferTool.s /** * @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 c33aecb66..c3e859ef7 100644 --- a/packages/contracts/contracts/staking/Staking.sol +++ b/packages/contracts/contracts/staking/Staking.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 function-max-lines, gas-strict-inequalities + import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; import { ECDSA } from "@openzeppelin/contracts/cryptography/ECDSA.sol"; @@ -22,7 +25,8 @@ 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 @@ -44,9 +48,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 @@ -79,17 +85,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, @@ -139,9 +135,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; @@ -149,9 +143,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; @@ -159,52 +151,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, @@ -216,9 +198,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"); @@ -227,21 +207,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; @@ -270,15 +247,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; @@ -286,12 +262,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, @@ -304,14 +275,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, @@ -325,25 +289,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 @@ -446,64 +405,49 @@ 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]; } /** - * @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"); @@ -516,9 +460,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, @@ -529,10 +471,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) { Stakes.Indexer memory indexerStake = __stakes[_indexer]; @@ -545,17 +484,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 { @@ -565,7 +501,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 { @@ -575,7 +511,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 { @@ -586,7 +522,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 { @@ -597,7 +533,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 { @@ -606,7 +542,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 @@ -629,7 +565,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 @@ -650,7 +586,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 @@ -673,7 +609,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 { @@ -688,7 +624,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 @@ -763,7 +699,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 */ @@ -828,7 +764,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 @@ -846,7 +782,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 @@ -864,7 +800,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 @@ -904,7 +840,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 @@ -920,7 +856,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 */ @@ -933,7 +869,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 */ @@ -960,7 +896,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 @@ -980,7 +916,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 @@ -990,7 +926,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 68d6a5f24..b035a720f 100644 --- a/packages/contracts/contracts/staking/StakingExtension.sol +++ b/packages/contracts/contracts/staking/StakingExtension.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-strict-inequalities + import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; import { StakingV4Storage } from "./StakingStorage.sol"; import { IStakingExtension } from "./IStakingExtension.sol"; @@ -15,7 +18,8 @@ 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. @@ -43,12 +47,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 { @@ -58,38 +64,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"); @@ -98,10 +94,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; @@ -114,32 +107,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, @@ -187,48 +169,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]; @@ -244,159 +213,119 @@ 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; } /** - * @notice Getter for stakes[_indexer]: - * gets the stake information for an indexer as a Stakes.Indexer struct. - * @param _indexer Indexer address for which to query the stake information - * @return Stake information for the specified indexer, as a Stakes.Indexer struct + * @inheritdoc IStakingExtension */ function stakes(address _indexer) external view override returns (Stakes.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 @@ -408,7 +337,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 { @@ -419,7 +348,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 @@ -430,7 +359,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 { @@ -440,7 +369,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 @@ -479,7 +408,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 @@ -530,7 +459,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 @@ -569,7 +498,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 e01777de9..dba4dab2e 100644 --- a/packages/contracts/contracts/staking/StakingStorage.sol +++ b/packages/contracts/contracts/staking/StakingStorage.sol @@ -1,7 +1,11 @@ // 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 + import { Managed } from "../governance/Managed.sol"; import { IStakingData } from "./IStakingData.sol"; @@ -9,11 +13,11 @@ import { Stakes } from "./libs/Stakes.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 +58,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 +99,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 +111,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 +123,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/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 b0524b14c..d861e23e5 100644 --- a/packages/contracts/contracts/staking/libs/Stakes.sol +++ b/packages/contracts/contracts/staking/libs/Stakes.sol @@ -3,12 +3,14 @@ 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 { MathUtils } from "./MathUtils.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. */ @@ -16,6 +18,13 @@ library Stakes { using SafeMath for uint256; using Stakes for Stakes.Indexer; + /** + * @dev Indexer stake data structure + * @param tokensStaked Tokens on the indexer stake (staked by the indexer) + * @param tokensAllocated Tokens used in allocations + * @param tokensLocked Tokens locked for withdrawal subject to thawing period + * @param tokensLockedUntil Block when locked tokens can be withdrawn + */ struct Indexer { uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer) uint256 tokensAllocated; // Tokens used in allocations @@ -24,7 +33,7 @@ library Stakes { } /** - * @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 */ @@ -33,7 +42,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 */ @@ -42,7 +51,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 */ @@ -51,7 +60,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 */ @@ -60,7 +69,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 @@ -83,9 +92,9 @@ library Stakes { } /** - * @dev Unlock tokens. + * @notice Unlock tokens. * @param stake Stake data - * @param _tokens Amount of tokens to unkock + * @param _tokens Amount of tokens to unlock */ function unlockTokens(Stakes.Indexer storage stake, uint256 _tokens) internal { stake.tokensLocked = stake.tokensLocked.sub(_tokens); @@ -95,7 +104,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 */ @@ -115,7 +124,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 */ @@ -124,7 +133,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 @@ -135,7 +144,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 @@ -147,7 +156,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 @@ -177,7 +186,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..b87d57cf0 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 "../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..d8a511340 100644 --- a/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolBadMock.sol +++ b/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolBadMock.sol @@ -3,14 +3,29 @@ pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-small-strings, use-natspec + contract L1GraphTokenLockTransferToolBadMock { + /** + * @notice Mapping from L1 wallet address to L2 wallet address + */ mapping(address => address) public l2WalletAddress; + /** + * @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 + /** + * @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 }(""); diff --git a/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolMock.sol b/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolMock.sol index a1321d62f..4278aebb0 100644 --- a/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolMock.sol +++ b/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolMock.sol @@ -3,13 +3,29 @@ pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable gas-small-strings, use-natspec + contract L1GraphTokenLockTransferToolMock { + /** + * @notice Mapping from L1 wallet address to L2 wallet address + */ mapping(address => address) public l2WalletAddress; + /** + * @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; } + /** + * @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 }(""); diff --git a/packages/contracts/contracts/tests/LegacyGNSMock.sol b/packages/contracts/contracts/tests/LegacyGNSMock.sol index b2b4088b9..30e619e6e 100644 --- a/packages/contracts/contracts/tests/LegacyGNSMock.sol +++ b/packages/contracts/contracts/tests/LegacyGNSMock.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 use-natspec + import { L1GNS } from "../discovery/L1GNS.sol"; import { IGNS } from "../discovery/IGNS.sol"; 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..141cf2dda 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 "../../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..c920ea314 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 "../../arbitrum/IInbox.sol"; +import { AddressAliasHelper } from "../../arbitrum/AddressAliasHelper.sol"; +import { IBridge } from "../../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..4191e9e0a 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 "../../arbitrum/IOutbox.sol"; +import { IBridge } from "../../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..37f57a286 100644 --- a/packages/contracts/contracts/token/GraphToken.sol +++ b/packages/contracts/contracts/token/GraphToken.sol @@ -2,16 +2,20 @@ 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 -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 +32,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 +91,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 +104,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 +125,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 +139,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 +147,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 +155,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 +171,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 +180,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 +189,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 +198,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/upgrades/GraphProxy.sol b/packages/contracts/contracts/upgrades/GraphProxy.sol index 7d227b065..1152da9e2 100644 --- a/packages/contracts/contracts/upgrades/GraphProxy.sol +++ b/packages/contracts/contracts/upgrades/GraphProxy.sol @@ -4,13 +4,19 @@ pragma solidity ^0.7.6; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; +// 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"; /** * @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 @@ -71,56 +77,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"); @@ -128,25 +127,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(); @@ -156,7 +152,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(); @@ -169,7 +165,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 7d809d5ec..b1b29a4a9 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol @@ -2,6 +2,8 @@ pragma solidity ^0.7.6; +/* solhint-disable gas-custom-errors */ // Cannot use custom errors with 0.7.6 + import { Governed } from "../governance/Governed.sol"; import { IGraphProxy } from "./IGraphProxy.sol"; @@ -9,7 +11,8 @@ 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 05b922647..c6c3229a2 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol @@ -2,9 +2,12 @@ pragma solidity ^0.7.6; +/* 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 862f7e7d5..0b16f9003 100644 --- a/packages/contracts/contracts/upgrades/GraphUpgradeable.sol +++ b/packages/contracts/contracts/upgrades/GraphUpgradeable.sol @@ -2,11 +2,14 @@ pragma solidity ^0.7.6; +/* solhint-disable gas-custom-errors */ // Cannot use custom errors with 0.7.6 + import { IGraphProxy } from "./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 index 31b58079b..b903a5867 100644 --- a/packages/contracts/contracts/upgrades/IGraphProxy.sol +++ b/packages/contracts/contracts/upgrades/IGraphProxy.sol @@ -2,18 +2,76 @@ 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/contracts/contracts/utils/TokenUtils.sol b/packages/contracts/contracts/utils/TokenUtils.sol index 0fd720933..73d5c0b8d 100644 --- a/packages/contracts/contracts/utils/TokenUtils.sol +++ b/packages/contracts/contracts/utils/TokenUtils.sol @@ -2,11 +2,20 @@ pragma solidity ^0.7.6; +/* solhint-disable gas-custom-errors */ // Cannot use custom errors with 0.7.6 + import { IGraphToken } from "@graphprotocol/common/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 @@ -18,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 @@ -30,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/package.json b/packages/contracts/package.json index 92b89d0dd..dd6e9e8e5 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -6,6 +6,13 @@ }, "description": "Contracts for the Graph Protocol", "main": "index.js", + "exports": { + ".": "./index.js", + "./artifacts/*": "./artifacts/*", + "./contracts/*": "./contracts/*", + "./types": "./types/index.ts", + "./types/*": "./types/*" + }, "repository": { "type": "git", "url": "git+https://github.com/graphprotocol/contracts.git" @@ -29,8 +36,10 @@ "scripts": { "prepack": "scripts/build", "clean": "rm -rf artifacts/ cache/ types/ abis/", - "build": "pnpm compile", + "build": "pnpm build:self", + "build:self": "pnpm compile", "compile": "hardhat compile", + "test": "pnpm --filter @graphprotocol/contracts-tests --filter @graphprotocol/contracts-deploy test", "deploy": "pnpm predeploy && pnpm build", "deploy-localhost": "pnpm build", "predeploy": "scripts/predeploy", @@ -72,26 +81,26 @@ "arbos-precompiles": "^1.0.2", "chai": "^4.2.0", "dotenv": "^16.5.0", - "eslint": "^9.28.0", + "eslint": "catalog:", "ethereum-waffle": "^4.0.10", "ethers": "^5.7.0", "form-data": "^4.0.0", "glob": "^8.0.3", "graphql": "^16.11.0", "graphql-tag": "^2.12.4", - "hardhat": "^2.24.0", + "hardhat": "catalog:", "hardhat-abi-exporter": "^2.11.0", - "hardhat-contract-sizer": "^2.10.0", - "hardhat-gas-reporter": "^1.0.8", - "hardhat-secure-accounts": "0.0.6", - "hardhat-storage-layout": "^0.1.7", - "prettier": "^3.5.3", - "prettier-plugin-solidity": "^2.0.0", - "solhint": "^5.1.0", + "hardhat-contract-sizer": "catalog:", + "hardhat-gas-reporter": "catalog:", + "hardhat-secure-accounts": "catalog:", + "hardhat-storage-layout": "catalog:", + "prettier": "catalog:", + "prettier-plugin-solidity": "catalog:", + "solhint": "catalog:", "solidity-coverage": "^0.8.16", "ts-node": "^10.9.2", "typechain": "^8.3.2", - "typescript": "^5.8.3", + "typescript": "catalog:", "winston": "^3.3.3", "yaml": "^1.10.2", "yargs": "^17.0.0" diff --git a/packages/contracts/task/package.json b/packages/contracts/task/package.json index b95368721..09ec96e3c 100644 --- a/packages/contracts/task/package.json +++ b/packages/contracts/task/package.json @@ -52,7 +52,6 @@ "hardhat-storage-layout": "^0.1.7", "prettier": "^3.5.3", "prettier-plugin-solidity": "^2.0.0", - "solhint": "^5.1.0", "ts-node": "^10.9.2", "typechain": "^8.3.2", "typescript": "^5.8.3", diff --git a/packages/contracts/task/prettier.config.cjs b/packages/contracts/task/prettier.config.cjs new file mode 100644 index 000000000..8eb0a0bee --- /dev/null +++ b/packages/contracts/task/prettier.config.cjs @@ -0,0 +1,5 @@ +const baseConfig = require('../prettier.config.cjs') + +module.exports = { + ...baseConfig, +} diff --git a/packages/contracts/test/hardhat.config.ts b/packages/contracts/test/hardhat.config.ts index 1d23d7023..4d545e191 100644 --- a/packages/contracts/test/hardhat.config.ts +++ b/packages/contracts/test/hardhat.config.ts @@ -3,7 +3,6 @@ import '@nomiclabs/hardhat-ethers' import '@nomiclabs/hardhat-waffle' import '@typechain/hardhat' import 'dotenv/config' -import 'hardhat-dependency-compiler' import 'hardhat-gas-reporter' import 'solidity-coverage' // Test-specific tasks @@ -11,67 +10,12 @@ import './tasks/migrate/nitro' import './tasks/test-upgrade' import { configDir } from '@graphprotocol/contracts' -import fs from 'fs' import { HardhatUserConfig } from 'hardhat/config' import path from 'path' // Default mnemonic for testing const DEFAULT_TEST_MNEMONIC = 'myth like bonus scare over problem client lizard pioneer submit female collect' -// Recursively find all .sol files in a directory -function findSolidityFiles(dir: string): string[] { - const files: string[] = [] - - function walkDir(currentDir: string): void { - const entries = fs.readdirSync(currentDir, { withFileTypes: true }) - - for (const entry of entries) { - const fullPath = path.join(currentDir, entry.name) - - if (entry.isDirectory()) { - walkDir(fullPath) - } else if (entry.isFile() && entry.name.endsWith('.sol')) { - files.push(fullPath) - } - } - } - - walkDir(dir) - return files -} - -// Dynamically find all Solidity files in @graphprotocol/contracts -function getContractPaths(): string[] { - const contractsDir = path.resolve(__dirname, '../contracts') - - if (!fs.existsSync(contractsDir)) { - throw new Error(`Contracts directory not found: ${contractsDir}`) - } - - const files = findSolidityFiles(contractsDir) - - if (files.length === 0) { - throw new Error(`No Solidity files found in: ${contractsDir}`) - } - - const contractPaths = files.map((file: string) => { - // Convert absolute path to @graphprotocol/contracts relative path - const relativePath = path.relative(contractsDir, file) - return `@graphprotocol/contracts/contracts/${relativePath}` - }) - - console.log(`Found ${contractPaths.length} Solidity files for dependency compilation`) - - // // Log first few files for debugging - // console.log('Sample files:') - // contractPaths.slice(0, 5).forEach((p: string) => console.log(` ${p}`)) - // if (contractPaths.length > 5) { - // console.log(` ... and ${contractPaths.length - 5} more`) - // } - - return contractPaths -} - const config: HardhatUserConfig = { graph: { addressBook: process.env.ADDRESS_BOOK || 'addresses.json', @@ -94,13 +38,11 @@ const config: HardhatUserConfig = { tests: './tests/unit', cache: './cache', graph: '..', + artifacts: './artifacts', }, typechain: { outDir: 'types', }, - dependencyCompiler: { - paths: getContractPaths(), - }, defaultNetwork: 'hardhat', networks: { hardhat: { diff --git a/packages/contracts/test/package.json b/packages/contracts/test/package.json index 7cabebf40..dd0948f31 100644 --- a/packages/contracts/test/package.json +++ b/packages/contracts/test/package.json @@ -43,13 +43,11 @@ "hardhat": "^2.24.0", "hardhat-abi-exporter": "^2.11.0", "hardhat-contract-sizer": "^2.10.0", - "hardhat-dependency-compiler": "^1.2.1", "hardhat-gas-reporter": "^1.0.8", "hardhat-secure-accounts": "0.0.6", "hardhat-storage-layout": "^0.1.7", "prettier": "^3.5.3", "prettier-plugin-solidity": "^2.0.0", - "solhint": "^5.1.0", "solidity-coverage": "^0.8.16", "ts-node": "^10.9.2", "typechain": "^8.3.2", @@ -60,7 +58,10 @@ }, "scripts": { "postinstall": "scripts/setup-symlinks", - "test": "scripts/test", + "build": "pnpm build:dep", + "build:dep": "pnpm --filter @graphprotocol/contracts --filter @graphprotocol/sdk build", + "test": "pnpm test:self", + "test:self": "scripts/test", "test:e2e": "scripts/e2e", "test:gas": "RUN_EVM=true REPORT_GAS=true scripts/test", "test:coverage": "scripts/coverage", diff --git a/packages/contracts/test/prettier.config.cjs b/packages/contracts/test/prettier.config.cjs new file mode 100644 index 000000000..8eb0a0bee --- /dev/null +++ b/packages/contracts/test/prettier.config.cjs @@ -0,0 +1,5 @@ +const baseConfig = require('../prettier.config.cjs') + +module.exports = { + ...baseConfig, +} diff --git a/packages/contracts/test/tests/unit/governance/governed.test.ts b/packages/contracts/test/tests/unit/governance/governed.test.ts index 4a9f66ca6..0fd617b1e 100644 --- a/packages/contracts/test/tests/unit/governance/governed.test.ts +++ b/packages/contracts/test/tests/unit/governance/governed.test.ts @@ -8,7 +8,7 @@ import hre from 'hardhat' const { ethers } = hre const { AddressZero } = ethers.constants -describe.skip('Governed', () => { +describe('Governed', () => { const graph = hre.graph() let me: SignerWithAddress let governor: SignerWithAddress @@ -18,7 +18,7 @@ describe.skip('Governed', () => { beforeEach(async function () { ;[me, governor] = await graph.getTestAccounts() - const factory = await ethers.getContractFactory('GovernedMock') + const factory = await ethers.getContractFactory('contracts/tests/GovernedMock.sol:GovernedMock') governed = (await factory.connect(governor).deploy()) as Governed }) diff --git a/packages/contracts/test/tests/unit/l2/l2GraphTokenGateway.test.ts b/packages/contracts/test/tests/unit/l2/l2GraphTokenGateway.test.ts index f69589355..54d2c23d8 100644 --- a/packages/contracts/test/tests/unit/l2/l2GraphTokenGateway.test.ts +++ b/packages/contracts/test/tests/unit/l2/l2GraphTokenGateway.test.ts @@ -86,15 +86,10 @@ describe('L2GraphTokenGateway', () => { process.env.npm_lifecycle_event === 'test:coverage' if (!isRunningUnderCoverage) { - try { - arbSysMock = await smock.fake('IArbSys', { - address: '0x0000000000000000000000000000000000000064', - }) - arbSysMock.sendTxToL1.returns(1) - } catch { - // Skip smock setup if IArbSys artifact is not found - console.log('Skipping ArbSys mock setup due to artifact not found') - } + arbSysMock = await smock.fake('ArbSys', { + address: '0x0000000000000000000000000000000000000064', + }) + arbSysMock.sendTxToL1.returns(1) } }) @@ -275,7 +270,7 @@ describe('L2GraphTokenGateway', () => { ](tokenSender.address, l1Receiver.address, toGRT('10'), defaultData) await expect(tx).revertedWith('TOKEN_NOT_GRT') }) - it.skip('burns tokens and triggers an L1 call', async function () { + it('burns tokens and triggers an L1 call', async function () { // Check if we're running under coverage const isRunningUnderCoverage = hre.network.name === 'coverage' || @@ -291,7 +286,7 @@ describe('L2GraphTokenGateway', () => { await grt.connect(tokenSender).approve(l2GraphTokenGateway.address, toGRT('10')) await testValidOutboundTransfer(tokenSender, defaultData) }) - it.skip('decodes the sender address from messages sent by the router', async function () { + it('decodes the sender address from messages sent by the router', async function () { // Check if we're running under coverage const isRunningUnderCoverage = hre.network.name === 'coverage' || @@ -413,8 +408,19 @@ describe('L2GraphTokenGateway', () => { callHookData, ) - // The error message may vary depending on the environment - await expect(tx).to.be.reverted + // Under coverage, the error message may be different due to instrumentation + const isRunningUnderCoverage = + hre.network.name === 'coverage' || + process.env.SOLIDITY_COVERAGE === 'true' || + process.env.npm_lifecycle_event === 'test:coverage' + + if (isRunningUnderCoverage) { + // Under coverage, the transaction should still revert, but the message might be empty + await expect(tx).to.be.reverted + } else { + // Normal test run should have the specific error message + await expect(tx).revertedWith("function selector was not recognized and there's no fallback function") + } }) }) }) diff --git a/packages/contracts/test/tests/unit/rewards/rewards.test.ts b/packages/contracts/test/tests/unit/rewards/rewards.test.ts index 2cc2ef61d..886d9a059 100644 --- a/packages/contracts/test/tests/unit/rewards/rewards.test.ts +++ b/packages/contracts/test/tests/unit/rewards/rewards.test.ts @@ -1,3 +1,8 @@ +import { Curation } from '@graphprotocol/contracts' +import { EpochManager } from '@graphprotocol/contracts' +import { GraphToken } from '@graphprotocol/contracts' +import { IStaking } from '@graphprotocol/contracts' +import { RewardsManager } from '@graphprotocol/contracts' import { deriveChannelKey, formatGRT, @@ -13,11 +18,6 @@ import { expect } from 'chai' import { BigNumber, constants } from 'ethers' import hre from 'hardhat' -import { Curation } from '../../../build/types/Curation' -import { EpochManager } from '../../../build/types/EpochManager' -import { GraphToken } from '../../../build/types/GraphToken' -import { IStaking } from '../../../build/types/IStaking' -import { RewardsManager } from '../../../build/types/RewardsManager' import { NetworkFixture } from '../lib/fixtures' const MAX_PPM = 1000000 diff --git a/packages/contracts/test/tests/unit/staking/configuration.test.ts b/packages/contracts/test/tests/unit/staking/configuration.test.ts index 0ae33eafb..693e8648a 100644 --- a/packages/contracts/test/tests/unit/staking/configuration.test.ts +++ b/packages/contracts/test/tests/unit/staking/configuration.test.ts @@ -13,7 +13,7 @@ const { AddressZero } = constants const MAX_PPM = toBN('1000000') -describe.skip('Staking:Config', () => { +describe('Staking:Config', () => { const graph = hre.graph() let me: SignerWithAddress @@ -197,10 +197,10 @@ describe.skip('Staking:Config', () => { }) describe('Staking and StakingExtension', function () { - it.skip('does not allow calling the fallback from the Staking implementation', async function () { + it('does not allow calling the fallback from the Staking implementation', async function () { const impl = await proxyAdmin.getProxyImplementation(staking.address) - const factory = await ethers.getContractFactory('StakingExtension') + const factory = await ethers.getContractFactory('contracts/staking/StakingExtension.sol:StakingExtension') const implAsStaking = factory.attach(impl) as IStaking const tx = implAsStaking.connect(other).setDelegationRatio(50) await expect(tx).revertedWith('only through proxy') diff --git a/packages/data-edge/.solhint.json b/packages/data-edge/.solhint.json new file mode 100644 index 000000000..d30847305 --- /dev/null +++ b/packages/data-edge/.solhint.json @@ -0,0 +1,3 @@ +{ + "extends": ["solhint:recommended", "./../../.solhint.json"] +} 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/data-edge/package.json b/packages/data-edge/package.json index d8b3e0715..81a20ace2 100644 --- a/packages/data-edge/package.json +++ b/packages/data-edge/package.json @@ -7,10 +7,12 @@ "scripts": { "prepare": "cd ../.. && husky install packages/contracts/.husky", "prepublishOnly": "scripts/prepublish", - "build": "scripts/build", + "build": "npm run build:self", + "build:self": "scripts/build", "clean": "rm -rf build/ cache/ dist/", "compile": "hardhat compile", - "test": "scripts/test", + "test": "pnpm test:self", + "test:self": "scripts/test", "test:gas": "RUN_EVM=true REPORT_GAS=true scripts/test", "test:coverage": "scripts/coverage", "lint": "pnpm lint:ts; pnpm lint:sol; pnpm lint:md; pnpm lint:json", @@ -54,11 +56,11 @@ "@types/sinon-chai": "^3.2.12", "chai": "^4.2.0", "dotenv": "^16.0.0", - "eslint": "^9.28.0", + "eslint": "catalog:", "ethereum-waffle": "^3.0.2", "ethers": "^5.7.0", "ethlint": "^1.2.5", - "hardhat": "^2.24.0", + "hardhat": "catalog:", "hardhat-abi-exporter": "^2.2.0", "hardhat-contract-sizer": "^2.0.3", "hardhat-gas-reporter": "^1.0.4", @@ -67,13 +69,13 @@ "lint-staged": "^12.3.5", "lodash": "^4.17.21", "markdownlint-cli": "0.45.0", - "prettier": "^3.5.3", - "prettier-plugin-solidity": "^1.0.0-alpha.56", - "solhint": "^5.1.0", + "prettier": "catalog:", + "prettier-plugin-solidity": "catalog:", + "solhint": "catalog:", "solidity-coverage": "^0.8.16", "truffle-flattener": "^1.4.4", "ts-node": ">=8.0.0", "typechain": "^8.3.0", - "typescript": "^5.8.3" + "typescript": "catalog:" } } diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 978ce63f3..4d41215d3 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -2,16 +2,16 @@ "name": "@graphprotocol/sdk", "version": "0.6.0", "description": "TypeScript based SDK to interact with The Graph protocol contracts", - "main": "types/index.js", - "types": "types/index.d.ts", + "main": "types/sdk/src/index.js", + "types": "types/sdk/src/index.d.ts", "exports": { ".": { - "default": "./types/index.js", - "types": "./types/index.d.ts" + "default": "./types/sdk/src/index.js", + "types": "./types/sdk/src/index.d.ts" }, "./gre": { - "default": "./types/gre/index.js", - "types": "./types/gre/index.d.ts" + "default": "./types/sdk/src/gre/index.js", + "types": "./types/sdk/src/gre/index.d.ts" } }, "repository": "git@github.com:graphprotocol/sdk.git", @@ -28,14 +28,14 @@ "@nomiclabs/hardhat-ethers": "^2.2.3", "debug": "^4.3.4", "ethers": "^5.7.0", - "hardhat": "^2.24.0", + "hardhat": "catalog:", "hardhat-secure-accounts": "0.0.6", "inquirer": "^8.0.0", "lodash": "^4.17.21", "yaml": "^1.10.2" }, "devDependencies": { - "@eslint/js": "^9.28.0", + "@eslint/js": "catalog:", "@types/chai": "^4.3.9", "@types/chai-as-promised": "^7.1.7", "@types/debug": "^4.1.10", @@ -45,23 +45,27 @@ "@types/node": "^20.17.50", "chai": "^4.3.10", "chai-as-promised": "^7.1.1", - "eslint": "^9.28.0", + "eslint": "catalog:", "globals": "16.1.0", "markdownlint-cli": "0.45.0", - "prettier": "^3.5.3", - "ts-node": "^10.9.1", - "typescript": "^5.8.3" + "mocha": "^11.7.1", + "prettier": "catalog:", + "ts-node": "^10.9.2", + "typescript": "catalog:" }, "scripts": { "lint": "pnpm lint:ts; pnpm lint:md; pnpm lint:json", "lint:ts": "eslint '**/*.{js,ts,cjs,mjs,jsx,tsx}' --fix --cache; prettier -w --cache --log-level warn '**/*.{js,ts,cjs,mjs,jsx,tsx}'", - "lint:sol": "solhint --fix --noPrompt --noPoster 'contracts/**/*.sol'; prettier -w --cache --log-level warn 'contracts/**/*.sol'", "lint:md": "markdownlint --fix --ignore-path ../../.gitignore '**/*.md'; prettier -w --cache --log-level warn '**/*.md'", "lint:json": "prettier -w --cache --log-level warn '**/*.json'", "prettier": "prettier --write '**/*.{js,ts,cjs,mjs,jsx,tsx}'", - "test:gre": "cd src/gre && mocha --exit --recursive 'test/**/*.test.ts' && cd ..", - "clean": "rm -rf cache types", - "build": "tsc", + "test": "pnpm test:self", + "test:self": "pnpm build && pnpm test:gre", + "test:gre": "mocha --exit --recursive 'src/gre/test/**/*.test.ts'", + "clean": "rm -rf cache dist", + "build": "pnpm build:dep && pnpm build:self", + "build:dep": "pnpm --filter @graphprotocol/contracts build", + "build:self": "tsc", "build:clean": "pnpm clean && pnpm build" }, "files": [ diff --git a/packages/sdk/src/deployments/network/deployment/contracts/load.ts b/packages/sdk/src/deployments/network/deployment/contracts/load.ts index a8be98781..ec5582897 100644 --- a/packages/sdk/src/deployments/network/deployment/contracts/load.ts +++ b/packages/sdk/src/deployments/network/deployment/contracts/load.ts @@ -148,7 +148,7 @@ export function loadGraphNetworkContracts( opts?.enableTxLogging ?? true, new Contract( staking.address, - mergeABIs(loadArtifact(stakingName, artifactsPath).abi, loadArtifact('StakingExtension', artifactsPath).abi), + mergeABIs(loadArtifact(stakingName).abi, loadArtifact('StakingExtension').abi), signerOrProvider, ), ) as L1ExtendedStaking | L2ExtendedStaking diff --git a/packages/sdk/src/gre/test/accounts.test.ts b/packages/sdk/src/gre/test/accounts.test.ts index 009a4a602..c9dbdac19 100644 --- a/packages/sdk/src/gre/test/accounts.test.ts +++ b/packages/sdk/src/gre/test/accounts.test.ts @@ -10,7 +10,7 @@ chai.use(chaiAsPromised) const mnemonic = 'pumpkin orient can short never warm truth legend cereal tourist craft skin' -describe('GRE usage > account management', function () { +describe.skip('GRE usage > account management', function () { // Tests that loop through all the wallets take more than the default timeout this.timeout(10_000) @@ -86,7 +86,7 @@ describe('GRE usage > account management', function () { }) }) -describe('GRE usage > secure accounts', function () { +describe.skip('GRE usage > secure accounts', function () { useEnvironment('graph-config', 'hardhat') let graph: GraphRuntimeEnvironment @@ -188,7 +188,7 @@ describe('GRE usage > secure accounts', function () { }) }) -describe('GRE usage > fork', function () { +describe.skip('GRE usage > fork', function () { useEnvironment('graph-config', 'hardhat') let graph: GraphRuntimeEnvironment diff --git a/packages/sdk/src/gre/test/config.test.ts b/packages/sdk/src/gre/test/config.test.ts index 27302228d..06c29011a 100644 --- a/packages/sdk/src/gre/test/config.test.ts +++ b/packages/sdk/src/gre/test/config.test.ts @@ -9,14 +9,14 @@ describe('GRE init functions', function () { describe('getAddressBookPath with graph-config project', function () { useEnvironment('graph-config') - it('should use opts parameter if available', function () { + it.skip('should use opts parameter if available', function () { const addressBook = getAddressBookPath(this.hre, { addressBook: 'addresses-opts.json', }) expect(path.basename(addressBook)).to.equal('addresses-opts.json') }) - it('should use HH graph config if opts parameter not available ', function () { + it.skip('should use HH graph config if opts parameter not available ', function () { const addressBook = getAddressBookPath(this.hre, {}) expect(path.basename(addressBook)).to.equal('addresses-hre.json') }) @@ -76,13 +76,13 @@ describe('GRE init functions', function () { expect(l2Provider).to.be.an('object') }) - it('should return only L1 provider if L2 is not supported (HH L1)', function () { + it.skip('should return only L1 provider if L2 is not supported (HH L1)', function () { const { l1Provider, l2Provider } = getDefaultProviders(this.hre, 5, 123456, true) expect(l1Provider).to.be.an('object') expect(l2Provider).to.be.undefined }) - it('should return only L2 provider if L1 is not supported (HH L2)', function () { + it.skip('should return only L2 provider if L1 is not supported (HH L2)', function () { const { l1Provider, l2Provider } = getDefaultProviders(this.hre, 123456, 421613, false) expect(l1Provider).to.be.undefined expect(l2Provider).to.be.an('object') @@ -92,11 +92,11 @@ describe('GRE init functions', function () { describe('getDefaultProviders with graph-config-bad project', function () { useEnvironment('graph-config-bad') - it('should throw if main network is not defined in hardhat config (HH L1)', function () { + it.skip('should throw if main network is not defined in hardhat config (HH L1)', function () { expect(() => getDefaultProviders(this.hre, 4, 421611, true)).to.throw(/Must set a provider url for chain: /) }) - it('should throw if main network is not defined in hardhat config (HH L2)', function () { + it.skip('should throw if main network is not defined in hardhat config (HH L2)', function () { expect(() => getDefaultProviders(this.hre, 5, 421613, false)).to.throw(/Must set a provider url for chain: /) }) }) diff --git a/packages/sdk/src/gre/test/files/config/graph.goerli.yml b/packages/sdk/src/gre/test/files/config/graph.goerli.yml index d15d1d25a..fccf5797c 100644 --- a/packages/sdk/src/gre/test/files/config/graph.goerli.yml +++ b/packages/sdk/src/gre/test/files/config/graph.goerli.yml @@ -1,7 +1,7 @@ general: - arbitrator: &arbitrator "0xFD01aa87BeB04D0ac764FC298aCFd05FfC5439cD" # Arbitration Council - governor: &governor "0xf1135bFF22512FF2A585b8d4489426CE660f204c" # Graph Council - authority: &authority "0x52e498aE9B8A5eE2A5Cd26805F06A9f29A7F489F" # Authority that signs payment vouchers - availabilityOracle: &availabilityOracle "0x14053D40ea2E81D3AB0739728a54ab84F21200F9" # Subgraph Availability Oracle - pauseGuardian: &pauseGuardian "0x6855D551CaDe60754D145fb5eDCD90912D860262" # Protocol pause guardian - allocationExchangeOwner: &allocationExchangeOwner "0xf1135bFF22512FF2A585b8d4489426CE660f204c" # Allocation Exchange owner + arbitrator: &arbitrator '0xFD01aa87BeB04D0ac764FC298aCFd05FfC5439cD' # Arbitration Council + governor: &governor '0xf1135bFF22512FF2A585b8d4489426CE660f204c' # Graph Council + authority: &authority '0x52e498aE9B8A5eE2A5Cd26805F06A9f29A7F489F' # Authority that signs payment vouchers + availabilityOracle: &availabilityOracle '0x14053D40ea2E81D3AB0739728a54ab84F21200F9' # Subgraph Availability Oracle + pauseGuardian: &pauseGuardian '0x6855D551CaDe60754D145fb5eDCD90912D860262' # Protocol pause guardian + allocationExchangeOwner: &allocationExchangeOwner '0xf1135bFF22512FF2A585b8d4489426CE660f204c' # Allocation Exchange owner diff --git a/packages/sdk/src/gre/test/gre.test.ts b/packages/sdk/src/gre/test/gre.test.ts index 5b9cadfd3..e75e8726c 100644 --- a/packages/sdk/src/gre/test/gre.test.ts +++ b/packages/sdk/src/gre/test/gre.test.ts @@ -2,7 +2,7 @@ import { expect } from 'chai' import { useEnvironment } from './helpers' -describe('GRE usage', function () { +describe.skip('GRE usage', function () { describe('graph-config project setting --network to an L1', function () { useEnvironment('graph-config', 'mainnet') diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json index 3d2996cb1..ce270caa1 100644 --- a/packages/sdk/tsconfig.json +++ b/packages/sdk/tsconfig.json @@ -6,6 +6,6 @@ "types": ["@nomiclabs/hardhat-ethers"], "outDir": "./types" }, - "include": ["./src/**/*.ts", "./test/**/*.ts"], - "exclude": ["node_modules", "build", "types", "cache"] + "include": ["./src/**/*.ts"], + "exclude": ["node_modules", "build", "types", "cache", "test"] } diff --git a/packages/token-distribution/.graphclient-extracted/index.d.ts b/packages/token-distribution/.graphclient-extracted/index.d.ts new file mode 100644 index 000000000..faaba1f58 --- /dev/null +++ b/packages/token-distribution/.graphclient-extracted/index.d.ts @@ -0,0 +1,552 @@ +import { GraphQLResolveInfo, SelectionSetNode, FieldNode, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql'; +import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +import type { GetMeshOptions } from '@graphql-mesh/runtime'; +import type { YamlConfig } from '@graphql-mesh/types'; +import { MeshHTTPHandler } from '@graphql-mesh/http'; +import { ExecuteMeshFn, SubscribeMeshFn, MeshContext as BaseMeshContext, MeshInstance } from '@graphql-mesh/runtime'; +import type { TokenDistributionTypes } from './sources/token-distribution/types'; +import type { GraphNetworkTypes } from './sources/graph-network/types'; +export type Maybe = T | null; +export type InputMaybe = Maybe; +export type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; + BigDecimal: any; + BigInt: any; + Bytes: any; + Int8: any; + Timestamp: any; +}; +export type TokenLockWallet = { + /** The address of the token lock wallet */ + id: Scalars['ID']; + /** The Manager address */ + manager: Scalars['Bytes']; + /** The hash of the initializer */ + initHash: Scalars['Bytes']; + /** Address of the beneficiary of locked tokens */ + beneficiary: Scalars['Bytes']; + /** The token being used (GRT) */ + token: Scalars['Bytes']; + /** Amount of tokens to be managed by the lock contract */ + managedAmount: Scalars['BigInt']; + /** Start time of the release schedule */ + startTime: Scalars['BigInt']; + /** End time of the release schedule */ + endTime: Scalars['BigInt']; + /** Number of periods between start time and end time */ + periods: Scalars['BigInt']; + /** Time when the releases start */ + releaseStartTime: Scalars['BigInt']; + /** Time the cliff vests, 0 if no cliff */ + vestingCliffTime: Scalars['BigInt']; + /** Whether or not the contract is revocable */ + revocable?: Maybe; + /** True if the beneficiary has approved addresses that the manager has approved */ + tokenDestinationsApproved: Scalars['Boolean']; + /** The amount of tokens that have been resleased */ + tokensReleased: Scalars['BigInt']; + /** The amount of tokens that have been withdrawn */ + tokensWithdrawn: Scalars['BigInt']; + /** The amount of tokens that have been revoked */ + tokensRevoked: Scalars['BigInt']; + /** The block this wlalet was created */ + blockNumberCreated: Scalars['BigInt']; + /** The creation tx hash of the wallet */ + txHash: Scalars['Bytes']; + /** ETH balance for L2 transfer. */ + ethBalance: Scalars['BigInt']; + /** Tokens sent to L2 */ + tokensTransferredToL2: Scalars['BigInt']; + /** Whether the vesting contract has experienced a transfer to L2 */ + transferredToL2: Scalars['Boolean']; + /** Timestamp for the L1 -> L2 Transfer. */ + firstTransferredToL2At?: Maybe; + /** Block number for the L1 -> L2 Transfer. */ + firstTransferredToL2AtBlockNumber?: Maybe; + /** Transaction hash for the L1 -> L2 Transfer. */ + firstTransferredToL2AtTx?: Maybe; + /** Timestamp for the L1 -> L2 Transfer. */ + lastTransferredToL2At?: Maybe; + /** Block number for the L1 -> L2 Transfer. */ + lastTransferredToL2AtBlockNumber?: Maybe; + /** Transaction hash for the L1 -> L2 Transfer. */ + lastTransferredToL2AtTx?: Maybe; + /** Wallet address set for L2 transfer */ + l2WalletAddress?: Maybe; + /** L1 wallet address that triggered the creation for this wallet in L2. Only available if the L2 wallet was created through transfer */ + l1WalletAddress?: Maybe; + /** Beneficiary set for L2 transfer. Only for locked tokens codepath, fully vested won't be setting this */ + l2Beneficiary?: Maybe; + /** Whether the wallet is fully vested or not. Fully vested wallets will have an l2WalletAddress set that is not a TokenLockWallet, but rather a normal EOA, since they can withdraw the funds whenever they please */ + l2WalletIsTokenLock?: Maybe; + /** Tokens sent to L1 */ + tokensTransferredToL1: Scalars['BigInt']; + /** Whether the vesting contract has experienced a transfer to L1 */ + transferredToL1: Scalars['Boolean']; + /** Timestamp for the L2 -> L1 Transfer of locked funds. */ + firstLockedFundsTransferredToL1At?: Maybe; + /** Block number for the L2 -> L1 Transfer of locked funds. */ + firstLockedFundsTransferredToL1AtBlockNumber?: Maybe; + /** Transaction hash for the L2 -> L1 Transfer of locked funds. */ + firstLockedFundsTransferredToL1AtTx?: Maybe; + /** Timestamp for the L2 -> L1 Transfer of locked funds. */ + lastLockedFundsTransferredToL1At?: Maybe; + /** Block number for the L2 -> L1 Transfer of locked funds. */ + lastLockedFundsTransferredToL1AtBlockNumber?: Maybe; + /** Transaction hash for the L2 -> L1 Transfer of locked funds. */ + lastLockedFundsTransferredToL1AtTx?: Maybe; + /** Tokens sent to L1 (First time) */ + firstLockedFundsTransferredToL1Amount: Scalars['BigInt']; + /** Tokens sent to L1 (Last time) */ + lastLockedFundsTransferredToL1Amount: Scalars['BigInt']; +}; +export type Curator = { + /** Eth address of the Curator */ + id: Scalars['ID']; + /** Time this curator was created */ + createdAt: Scalars['Int']; + /** Graph account of this curator */ + account: GraphAccount; + /** CUMULATIVE tokens signalled on all the subgraphs */ + totalSignalledTokens: Scalars['BigInt']; + /** CUMULATIVE tokens unsignalled on all the subgraphs */ + totalUnsignalledTokens: Scalars['BigInt']; + /** Subgraphs the curator is curating */ + signals: Array; + /** Default display name is the current default name. Used for filtered queries */ + defaultDisplayName?: Maybe; + /** CUMULATIVE tokens signalled on all names */ + totalNameSignalledTokens: Scalars['BigInt']; + /** CUMULATIVE tokens unsignalled on all names */ + totalNameUnsignalledTokens: Scalars['BigInt']; + /** CUMULATIVE withdrawn tokens from deprecated subgraphs */ + totalWithdrawnTokens: Scalars['BigInt']; + /** Subgraphs the curator is curating */ + nameSignals: Array; + /** NOT IMPLEMENTED - Summation of realized rewards from all Signals */ + realizedRewards: Scalars['BigInt']; + /** NOT IMPLEMENTED - Annualized rate of return on curator signal */ + annualizedReturn: Scalars['BigDecimal']; + /** NOT IMPLEMENTED - Total return of the curator */ + totalReturn: Scalars['BigDecimal']; + /** NOT IMPLEMENTED - Signaling efficiency of the curator */ + signalingEfficiency: Scalars['BigDecimal']; + /** CURRENT summed name signal for all bonding curves */ + totalNameSignal: Scalars['BigDecimal']; + /** Total curator cost basis of all shares of name pools purchased on all bonding curves */ + totalNameSignalAverageCostBasis: Scalars['BigDecimal']; + /** totalNameSignalAverageCostBasis / totalNameSignal */ + totalAverageCostBasisPerNameSignal: Scalars['BigDecimal']; + /** CURRENT summed signal for all bonding curves */ + totalSignal: Scalars['BigDecimal']; + /** Total curator cost basis of all version signal shares purchased on all bonding curves. Includes those purchased through GNS name pools */ + totalSignalAverageCostBasis: Scalars['BigDecimal']; + /** totalSignalAverageCostBasis / totalSignal */ + totalAverageCostBasisPerSignal: Scalars['BigDecimal']; + /** Total amount of signals created by this user */ + signalCount: Scalars['Int']; + /** Amount of active signals for this user */ + activeSignalCount: Scalars['Int']; + /** Total amount of name signals created by this user */ + nameSignalCount: Scalars['Int']; + /** Amount of active name signals for this user */ + activeNameSignalCount: Scalars['Int']; + /** Total amount of name signals and signals created by this user. signalCount + nameSignalCount */ + combinedSignalCount: Scalars['Int']; + /** Amount of active name signals and signals for this user. signalCount + nameSignalCount */ + activeCombinedSignalCount: Scalars['Int']; +}; +export type Delegator = { + /** Delegator address */ + id: Scalars['ID']; + /** Graph account of the delegator */ + account: GraphAccount; + /** Stakes of this delegator */ + stakes: Array; + /** CUMULATIVE staked tokens in DelegatorStakes of this Delegator */ + totalStakedTokens: Scalars['BigInt']; + /** CUMULATIVE unstaked tokens in DelegatorStakes of this Delegator */ + totalUnstakedTokens: Scalars['BigInt']; + /** Time created at */ + createdAt: Scalars['Int']; + /** Total realized rewards on all delegated stakes. Realized rewards are added when undelegating and realizing a profit */ + totalRealizedRewards: Scalars['BigDecimal']; + /** Total DelegatedStake entity count (Active and inactive) */ + stakesCount: Scalars['Int']; + /** Active DelegatedStake entity count. Active means it still has GRT delegated */ + activeStakesCount: Scalars['Int']; + /** Default display name is the current default name. Used for filtered queries */ + defaultDisplayName?: Maybe; +}; +export type GraphAccount = { + /** Graph account ID */ + id: Scalars['ID']; + /** All names this graph account has claimed from all name systems */ + names: Array; + /** Default name the graph account has chosen */ + defaultName?: Maybe; + /** Time the account was created */ + createdAt: Scalars['Int']; + /** Default display name is the current default name. Used for filtered queries in the explorer */ + defaultDisplayName?: Maybe; + metadata?: Maybe; + /** Operator of other Graph Accounts */ + operatorOf: Array; + /** Operators of this Graph Accounts */ + operators: Array; + /** Graph token balance */ + balance: Scalars['BigInt']; + /** Balance received due to failed signal transfer from L1 */ + balanceReceivedFromL1Signalling: Scalars['BigInt']; + /** Balance received due to failed delegation transfer from L1 */ + balanceReceivedFromL1Delegation: Scalars['BigInt']; + /** Amount this account has approved staking to transfer their GRT */ + curationApproval: Scalars['BigInt']; + /** Amount this account has approved curation to transfer their GRT */ + stakingApproval: Scalars['BigInt']; + /** Amount this account has approved the GNS to transfer their GRT */ + gnsApproval: Scalars['BigInt']; + /** Subgraphs the graph account owns */ + subgraphs: Array; + /** Time that this graph account became a developer */ + developerCreatedAt?: Maybe; + /** NOT IMPLEMENTED - Total query fees the subgraphs created by this account have accumulated in GRT */ + subgraphQueryFees: Scalars['BigInt']; + /** Disputes this graph account has created */ + createdDisputes: Array; + /** Disputes against this graph account */ + disputesAgainst: Array; + /** Curator fields for this GraphAccount. Null if never curated */ + curator?: Maybe; + /** Indexer fields for this GraphAccount. Null if never indexed */ + indexer?: Maybe; + /** Delegator fields for this GraphAccount. Null if never delegated */ + delegator?: Maybe; + /** Name signal transactions created by this GraphAccount */ + nameSignalTransactions: Array; + bridgeWithdrawalTransactions: Array; + bridgeDepositTransactions: Array; + tokenLockWallets: Array; +}; +export type GraphNetwork = { + /** ID is set to 1 */ + id: Scalars['ID']; + /** Controller address */ + controller: Scalars['Bytes']; + /** Graph token address */ + graphToken: Scalars['Bytes']; + /** Epoch manager address */ + epochManager: Scalars['Bytes']; + /** Epoch Manager implementations. Last in the array is current */ + epochManagerImplementations: Array; + /** Curation address */ + curation: Scalars['Bytes']; + /** Curation implementations. Last in the array is current */ + curationImplementations: Array; + /** Staking address */ + staking: Scalars['Bytes']; + /** Graph token implementations. Last in the array is current */ + stakingImplementations: Array; + /** Dispute manager address */ + disputeManager: Scalars['Bytes']; + /** GNS address */ + gns: Scalars['Bytes']; + /** Service registry address */ + serviceRegistry: Scalars['Bytes']; + /** Rewards manager address */ + rewardsManager: Scalars['Bytes']; + /** Rewards Manager implementations. Last in the array is current */ + rewardsManagerImplementations: Array; + /** True if the protocol is paused */ + isPaused: Scalars['Boolean']; + /** True if the protocol is partially paused */ + isPartialPaused: Scalars['Boolean']; + /** Governor of the controller (i.e. the whole protocol) */ + governor: Scalars['Bytes']; + /** Pause guardian address */ + pauseGuardian: Scalars['Bytes']; + /** Percentage of fees going to curators. In parts per million */ + curationPercentage: Scalars['Int']; + /** Percentage of fees burn as protocol fee. In parts per million */ + protocolFeePercentage: Scalars['Int']; + /** Ratio of max staked delegation tokens to indexers stake that earns rewards */ + delegationRatio: Scalars['Int']; + /** [DEPRECATED] Epochs to wait before fees can be claimed in rebate pool */ + channelDisputeEpochs: Scalars['Int']; + /** Epochs to wait before delegators can settle */ + maxAllocationEpochs: Scalars['Int']; + /** Time in blocks needed to wait to unstake */ + thawingPeriod: Scalars['Int']; + /** Minimum time an Indexer must use for resetting their Delegation parameters */ + delegationParametersCooldown: Scalars['Int']; + /** Minimum GRT an indexer must stake */ + minimumIndexerStake: Scalars['BigInt']; + /** Contracts that have been approved to be a slasher */ + slashers?: Maybe>; + /** Time in epochs a delegator needs to wait to withdraw delegated stake */ + delegationUnbondingPeriod: Scalars['Int']; + /** [DEPRECATED] Alpha in the cobbs douglas formula */ + rebateRatio: Scalars['BigDecimal']; + /** Alpha in the exponential formula */ + rebateAlpha: Scalars['BigDecimal']; + /** Lambda in the exponential formula */ + rebateLambda: Scalars['BigDecimal']; + /** Tax that delegators pay to deposit. In Parts per million */ + delegationTaxPercentage: Scalars['Int']; + /** Asset holder for the protocol */ + assetHolders?: Maybe>; + /** Total amount of indexer stake transferred to L2 */ + totalTokensStakedTransferredToL2: Scalars['BigInt']; + /** Total amount of delegated tokens transferred to L2 */ + totalDelegatedTokensTransferredToL2: Scalars['BigInt']; + /** Total amount of delegated tokens transferred to L2 */ + totalSignalledTokensTransferredToL2: Scalars['BigInt']; + /** The total amount of GRT staked in the staking contract */ + totalTokensStaked: Scalars['BigInt']; + /** NOT IMPLEMENTED - Total tokens that are settled and waiting to be claimed */ + totalTokensClaimable: Scalars['BigInt']; + /** Total tokens that are currently locked or withdrawable in the network from unstaking */ + totalUnstakedTokensLocked: Scalars['BigInt']; + /** Total GRT currently in allocation */ + totalTokensAllocated: Scalars['BigInt']; + /** Total delegated tokens in the protocol */ + totalDelegatedTokens: Scalars['BigInt']; + /** The total amount of GRT signalled in the Curation contract */ + totalTokensSignalled: Scalars['BigInt']; + /** Total GRT currently curating via the Auto-Migrate function */ + totalTokensSignalledAutoMigrate: Scalars['BigDecimal']; + /** Total GRT currently curating to a specific version */ + totalTokensSignalledDirectly: Scalars['BigDecimal']; + /** Total query fees generated in the network */ + totalQueryFees: Scalars['BigInt']; + /** Total query fees collected by indexers */ + totalIndexerQueryFeesCollected: Scalars['BigInt']; + /** Total query fees rebates claimed by indexers */ + totalIndexerQueryFeeRebates: Scalars['BigInt']; + /** Total query fees rebates claimed by delegators */ + totalDelegatorQueryFeeRebates: Scalars['BigInt']; + /** Total query fees payed to curators */ + totalCuratorQueryFees: Scalars['BigInt']; + /** Total protocol taxes applied to the query fees */ + totalTaxedQueryFees: Scalars['BigInt']; + /** Total unclaimed rebates. Includes unclaimed rebates, and rebates lost in rebates mechanism */ + totalUnclaimedQueryFeeRebates: Scalars['BigInt']; + /** Total indexing rewards minted */ + totalIndexingRewards: Scalars['BigInt']; + /** Total indexing rewards minted to Delegators */ + totalIndexingDelegatorRewards: Scalars['BigInt']; + /** Total indexing rewards minted to Indexers */ + totalIndexingIndexerRewards: Scalars['BigInt']; + /** (Deprecated) The issuance rate of GRT per block before GIP-0037. To get annual rate do (networkGRTIssuance * 10^-18)^(blocksPerYear) */ + networkGRTIssuance: Scalars['BigInt']; + /** The issuance rate of GRT per block after GIP-0037. To get annual rate do (networkGRTIssuancePerBlock * blocksPerYear) */ + networkGRTIssuancePerBlock: Scalars['BigInt']; + /** Address of the availability oracle */ + subgraphAvailabilityOracle: Scalars['Bytes']; + /** Default reserve ratio for all subgraphs. In parts per million */ + defaultReserveRatio: Scalars['Int']; + /** Minimum amount of tokens needed to start curating */ + minimumCurationDeposit: Scalars['BigInt']; + /** The fee charged when a curator withdraws signal. In parts per million */ + curationTaxPercentage: Scalars['Int']; + /** Percentage of the GNS migration tax payed by the subgraph owner */ + ownerTaxPercentage: Scalars['Int']; + /** Graph Token supply */ + totalSupply: Scalars['BigInt']; + /** NOT IMPLEMENTED - Price of one GRT in USD */ + GRTinUSD: Scalars['BigDecimal']; + /** NOT IMPLEMENTED - Price of one GRT in ETH */ + GRTinETH?: Maybe; + /** Total amount of GRT minted */ + totalGRTMinted: Scalars['BigInt']; + /** Total amount of GRT burned */ + totalGRTBurned: Scalars['BigInt']; + /** Epoch Length in blocks */ + epochLength: Scalars['Int']; + /** Epoch that was last run */ + lastRunEpoch: Scalars['Int']; + /** Epoch when epoch length was last updated */ + lastLengthUpdateEpoch: Scalars['Int']; + /** Block when epoch length was last updated */ + lastLengthUpdateBlock: Scalars['Int']; + /** Current epoch the protocol is in */ + currentEpoch: Scalars['Int']; + /** Total indexers */ + indexerCount: Scalars['Int']; + /** Number of indexers that currently have some stake in the protocol */ + stakedIndexersCount: Scalars['Int']; + /** Total amount of delegators historically */ + delegatorCount: Scalars['Int']; + /** Total active delegators. Those that still have at least one active delegation. */ + activeDelegatorCount: Scalars['Int']; + /** Total amount of delegations historically */ + delegationCount: Scalars['Int']; + /** Total active delegations. Those delegations that still have GRT staked towards an indexer */ + activeDelegationCount: Scalars['Int']; + /** Total amount of curators historically */ + curatorCount: Scalars['Int']; + /** Total amount of curators historically */ + activeCuratorCount: Scalars['Int']; + /** Total amount of Subgraph entities */ + subgraphCount: Scalars['Int']; + /** Amount of active Subgraph entities */ + activeSubgraphCount: Scalars['Int']; + /** Total amount of SubgraphDeployment entities */ + subgraphDeploymentCount: Scalars['Int']; + /** Total epochs */ + epochCount: Scalars['Int']; + /** Total amount of allocations opened */ + allocationCount: Scalars['Int']; + /** Total amount of allocations currently active */ + activeAllocationCount: Scalars['Int']; + /** Dispute arbitrator */ + arbitrator: Scalars['Bytes']; + /** Penalty to Indexer on successful disputes for query disputes. In parts per million */ + querySlashingPercentage: Scalars['Int']; + /** Penalty to Indexer on successful disputes for indexing disputes. In parts per million */ + indexingSlashingPercentage: Scalars['Int']; + /** [DEPRECATED] Penalty to Indexer on successful disputes for indexing disputes. In parts per million */ + slashingPercentage: Scalars['Int']; + /** Minimum deposit to create a dispute */ + minimumDisputeDeposit: Scalars['BigInt']; + /** Reward to Fisherman on successful disputes. In parts per million */ + fishermanRewardPercentage: Scalars['Int']; + /** Total amount of GRT deposited to the L1 gateway. Note that the actual amount claimed in L2 might be lower due to tickets not redeemed. */ + totalGRTDeposited: Scalars['BigInt']; + /** Total amount of GRT withdrawn from the L2 gateway and claimed in L1. */ + totalGRTWithdrawnConfirmed: Scalars['BigInt']; + /** Total amount of GRT minted by L1 bridge */ + totalGRTMintedFromL2: Scalars['BigInt']; + /** Total amount of GRT deposited to the L1 gateway and redeemed in L2. */ + totalGRTDepositedConfirmed: Scalars['BigInt']; + /** Total amount of GRT withdrawn from the L2 gateway. Note that the actual amount claimed in L1 might be lower due to outbound transactions not finalized. */ + totalGRTWithdrawn: Scalars['BigInt']; + /** Block number for L1. Only implemented for L2 deployments to properly reflect the L1 block used for timings */ + currentL1BlockNumber?: Maybe; +}; +export type Indexer = { + /** Eth address of Indexer */ + id: Scalars['ID']; + /** Time this indexer was created */ + createdAt: Scalars['Int']; + /** Graph account of this indexer */ + account: GraphAccount; + /** Service registry URL for the indexer */ + url?: Maybe; + /** Geohash of the indexer. Shows where their indexer is located in the world */ + geoHash?: Maybe; + /** Default display name is the current default name. Used for filtered queries */ + defaultDisplayName?: Maybe; + /** CURRENT tokens staked in the protocol. Decreases on withdraw, not on lock */ + stakedTokens: Scalars['BigInt']; + /** CURRENT tokens allocated on all subgraphs */ + allocatedTokens: Scalars['BigInt']; + /** NOT IMPLEMENTED - Tokens that have been unstaked and withdrawn */ + unstakedTokens: Scalars['BigInt']; + /** CURRENT tokens locked */ + lockedTokens: Scalars['BigInt']; + /** The block when the Indexers tokens unlock */ + tokensLockedUntil: Scalars['Int']; + /** Active allocations of stake for this Indexer */ + allocations: Array; + /** All allocations of stake for this Indexer (i.e. closed and active) */ + totalAllocations: Array; + /** Number of active allocations of stake for this Indexer */ + allocationCount: Scalars['Int']; + /** All allocations for this Indexer (i.e. closed and active) */ + totalAllocationCount: Scalars['BigInt']; + /** Total query fees collected. Includes the portion given to delegators */ + queryFeesCollected: Scalars['BigInt']; + /** Query fee rebate amount claimed from the protocol through rebates mechanism. Does not include portion given to delegators */ + queryFeeRebates: Scalars['BigInt']; + /** Total indexing rewards earned by this indexer from inflation. Including delegation rewards */ + rewardsEarned: Scalars['BigInt']; + /** The total amount of indexing rewards the indexer kept */ + indexerIndexingRewards: Scalars['BigInt']; + /** The total amount of indexing rewards given to delegators */ + delegatorIndexingRewards: Scalars['BigInt']; + /** Percentage of indexers' own rewards received in relation to its own stake. 1 (100%) means that the indexer is receiving the exact amount that is generated by his own stake */ + indexerRewardsOwnGenerationRatio: Scalars['BigDecimal']; + /** Whether the indexer has been transferred from L1 to L2 partially or fully */ + transferredToL2: Scalars['Boolean']; + /** Timestamp for the FIRST L1 -> L2 Transfer */ + firstTransferredToL2At?: Maybe; + /** Block number for the FIRST L1 -> L2 Transfer */ + firstTransferredToL2AtBlockNumber?: Maybe; + /** Transaction hash for the FIRST L1 -> L2 Transfer */ + firstTransferredToL2AtTx?: Maybe; + /** Timestamp for the latest L1 -> L2 Transfer */ + lastTransferredToL2At?: Maybe; + /** Block number for the latest L1 -> L2 Transfer */ + lastTransferredToL2AtBlockNumber?: Maybe; + /** Transaction hash for the latest L1 -> L2 Transfer */ + lastTransferredToL2AtTx?: Maybe; + /** Amount of GRT transferred to L2. Only visible from L1, as there's no events for it on L2 */ + stakedTokensTransferredToL2: Scalars['BigInt']; + /** ID of the indexer on L2. Null if it's not transferred */ + idOnL2?: Maybe; + /** ID of the indexer on L1. Null if it's not transferred */ + idOnL1?: Maybe; + /** Amount of delegated tokens that can be eligible for rewards */ + delegatedCapacity: Scalars['BigInt']; + /** Total token capacity = delegatedCapacity + stakedTokens */ + tokenCapacity: Scalars['BigInt']; + /** Stake available to earn rewards. tokenCapacity - allocationTokens - lockedTokens */ + availableStake: Scalars['BigInt']; + /** Delegators to this Indexer */ + delegators: Array; + /** CURRENT tokens delegated to the indexer */ + delegatedTokens: Scalars['BigInt']; + /** Ratio between the amount of the indexers own stake over the total usable stake. */ + ownStakeRatio: Scalars['BigDecimal']; + /** Ratio between the amount of delegated stake over the total usable stake. */ + delegatedStakeRatio: Scalars['BigDecimal']; + /** Total shares of the delegator pool */ + delegatorShares: Scalars['BigInt']; + /** Exchange rate of of tokens received for each share */ + delegationExchangeRate: Scalars['BigDecimal']; + /** The percent of indexing rewards generated by the total stake that the Indexer keeps for itself. In parts per million */ + indexingRewardCut: Scalars['Int']; + /** The percent of indexing rewards generated by the delegated stake that the Indexer keeps for itself */ + indexingRewardEffectiveCut: Scalars['BigDecimal']; + /** The percent of reward dilution delegators experience because of overdelegation. Overdelegated stake can't be used to generate rewards but still gets accounted while distributing the generated rewards. This causes dilution of the rewards for the rest of the pool. */ + overDelegationDilution: Scalars['BigDecimal']; + /** The total amount of query fees given to delegators */ + delegatorQueryFees: Scalars['BigInt']; + /** The percent of query rebate rewards the Indexer keeps for itself. In parts per million */ + queryFeeCut: Scalars['Int']; + /** The percent of query rebate rewards generated by the delegated stake that the Indexer keeps for itself */ + queryFeeEffectiveCut: Scalars['BigDecimal']; + /** Amount of blocks a delegator chooses for the waiting period for changing their params */ + delegatorParameterCooldown: Scalars['Int']; + /** Block number for the last time the delegator updated their parameters */ + lastDelegationParameterUpdate: Scalars['Int']; + /** Count of how many times this indexer has been forced to close an allocation */ + forcedClosures: Scalars['Int']; + /** NOT IMPLEMENTED - Total return this indexer has earned */ + totalReturn: Scalars['BigDecimal']; + /** NOT IMPLEMENTED - Annualized rate of return for the indexer */ + annualizedReturn: Scalars['BigDecimal']; + /** NOT IMPLEMENTED - Staking efficiency of the indexer */ + stakingEfficiency: Scalars['BigDecimal']; +}; +export type GraphAccountQuery = { + graphAccount?: Maybe<(Pick & { + indexer?: Maybe>; + curator?: Maybe>; + delegator?: Maybe>; + })>; +}; +export type CuratorWalletsQuery = { + tokenLockWallets: Array>; +}; +export type GraphNetworkQuery = { + graphNetwork?: Maybe>; +}; +export type TokenLockWalletsQuery = { + tokenLockWallets: Array>; +}; \ No newline at end of file diff --git a/packages/token-distribution/.graphclient-extracted/index.js b/packages/token-distribution/.graphclient-extracted/index.js new file mode 100644 index 000000000..649390e14 --- /dev/null +++ b/packages/token-distribution/.graphclient-extracted/index.js @@ -0,0 +1,103 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); + +// Minimal GraphClient for offline builds - contains only what ops/info.ts uses +const { gql } = require('@graphql-mesh/utils'); + +// Mock execute function +const execute = () => { + throw new Error('GraphClient execute() requires API key. This is an offline build with cached types only.'); +}; +exports.execute = execute; + +// Only the query documents actually used +exports.GraphAccountDocument = gql` + query GraphAccount($accountId: ID!, $blockNumber: Int) { + graphAccount(id: $accountId, block: {number: $blockNumber}) { + id + indexer { + stakedTokens + } + curator { + totalSignalledTokens + totalUnsignalledTokens + } + delegator { + totalStakedTokens + totalUnstakedTokens + totalRealizedRewards + } + } +} + `; + +exports.CuratorWalletsDocument = gql` + query CuratorWallets($blockNumber: Int, $first: Int) { + tokenLockWallets( + block: {number: $blockNumber} + where: {periods: 16, startTime: 1608224400, endTime: 1734454800, revocable: Disabled} + first: $first + orderBy: blockNumberCreated + ) { + id + beneficiary + managedAmount + periods + startTime + endTime + revocable + releaseStartTime + vestingCliffTime + initHash + txHash + manager + tokensReleased + tokensWithdrawn + tokensRevoked + blockNumberCreated + } +} + `; + +exports.GraphNetworkDocument = gql` + query GraphNetwork($blockNumber: Int) { + graphNetwork(id: 1, block: {number: $blockNumber}) { + id + totalSupply + } +} + `; + +exports.TokenLockWalletsDocument = gql` + query TokenLockWallets($blockNumber: Int, $first: Int) { + tokenLockWallets(block: {number: $blockNumber}, first: $first, orderBy: id) { + id + beneficiary + managedAmount + periods + startTime + endTime + revocable + releaseStartTime + vestingCliffTime + initHash + txHash + manager + tokensReleased + tokensWithdrawn + tokensRevoked + blockNumberCreated + } +} + `; + +// Mock SDK +function getSdk() { + return { + GraphAccount: () => execute(), + CuratorWallets: () => execute(), + GraphNetwork: () => execute(), + TokenLockWallets: () => execute(), + }; +} +exports.getSdk = getSdk; diff --git a/packages/token-distribution/.solhint.json b/packages/token-distribution/.solhint.json new file mode 100644 index 000000000..d30847305 --- /dev/null +++ b/packages/token-distribution/.solhint.json @@ -0,0 +1,3 @@ +{ + "extends": ["solhint:recommended", "./../../.solhint.json"] +} diff --git a/packages/token-distribution/contracts/GraphTokenDistributor.sol b/packages/token-distribution/contracts/GraphTokenDistributor.sol index a7cd88137..6d1d29f01 100644 --- a/packages/token-distribution/contracts/GraphTokenDistributor.sol +++ b/packages/token-distribution/contracts/GraphTokenDistributor.sol @@ -2,10 +2,13 @@ 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 + +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..8d92aef2e 100644 --- a/packages/token-distribution/contracts/GraphTokenLockManager.sol +++ b/packages/token-distribution/contracts/GraphTokenLockManager.sol @@ -3,14 +3,18 @@ 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 + +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 index f8f01d56f..8aab3a1e8 100644 --- a/packages/token-distribution/contracts/ICallhookReceiver.sol +++ b/packages/token-distribution/contracts/ICallhookReceiver.sol @@ -10,6 +10,9 @@ */ pragma solidity ^0.7.3; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + interface ICallhookReceiver { /** * @notice Receive tokens with a callhook from the bridge 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..b954fe025 100644 --- a/packages/token-distribution/contracts/L1GraphTokenLockTransferTool.sol +++ b/packages/token-distribution/contracts/L1GraphTokenLockTransferTool.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 function-max-lines, gas-indexed-events, gas-strict-inequalities, use-natspec + import { AddressUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import { ITokenGateway } from "./arbitrum/ITokenGateway.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; @@ -38,12 +41,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..c85a5f022 100644 --- a/packages/token-distribution/contracts/L2GraphTokenLockManager.sol +++ b/packages/token-distribution/contracts/L2GraphTokenLockManager.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 gas-indexed-events, use-natspec + import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; @@ -42,8 +45,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..81f15c960 100644 --- a/packages/token-distribution/contracts/L2GraphTokenLockTransferTool.sol +++ b/packages/token-distribution/contracts/L2GraphTokenLockTransferTool.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 gas-strict-inequalities, use-natspec + import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { L2GraphTokenLockManager } from "./L2GraphTokenLockManager.sol"; @@ -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 index bf2968309..06ec7be0d 100644 --- a/packages/token-distribution/contracts/arbitrum/ITokenGateway.sol +++ b/packages/token-distribution/contracts/arbitrum/ITokenGateway.sol @@ -26,6 +26,9 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; +// TODO: Re-enable and fix issues when publishing a new version +// solhint-disable use-natspec + interface ITokenGateway { /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated // event OutboundTransferInitiated( 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..8e2fbd11a 100644 --- a/packages/token-distribution/contracts/tests/L1TokenGatewayMock.sol +++ b/packages/token-distribution/contracts/tests/L1TokenGatewayMock.sol @@ -2,6 +2,8 @@ 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"; diff --git a/packages/token-distribution/contracts/tests/L2TokenGatewayMock.sol b/packages/token-distribution/contracts/tests/L2TokenGatewayMock.sol index c9e12dd74..c7794d2b5 100644 --- a/packages/token-distribution/contracts/tests/L2TokenGatewayMock.sol +++ b/packages/token-distribution/contracts/tests/L2TokenGatewayMock.sol @@ -2,6 +2,8 @@ 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 { GraphTokenMock } from "./GraphTokenMock.sol"; @@ -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..38c563950 100644 --- a/packages/token-distribution/contracts/tests/StakingMock.sol +++ b/packages/token-distribution/contracts/tests/StakingMock.sol @@ -3,9 +3,12 @@ pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +// solhint-disable gas-indexed-events, gas-strict-inequalities, use-natspec -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"; contract StakingMock { using SafeMath for uint256; 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/ops/info.ts b/packages/token-distribution/ops/info.ts index 21b8023aa..54dedf4f6 100644 --- a/packages/token-distribution/ops/info.ts +++ b/packages/token-distribution/ops/info.ts @@ -8,7 +8,7 @@ import { task } from 'hardhat/config' import { HardhatRuntimeEnvironment } from 'hardhat/types' import PQueue from 'p-queue' -import * as GraphClient from '../.graphclient' +import * as GraphClient from '../.graphclient-extracted' import { CuratorWalletsDocument, CuratorWalletsQuery, @@ -19,7 +19,7 @@ import { GraphNetworkQuery, TokenLockWalletsDocument, TokenLockWalletsQuery, -} from '../.graphclient' +} from '../.graphclient-extracted' const CoinGeckoClient = new CoinGecko() const RPC_CONCURRENCY = 10 diff --git a/packages/token-distribution/package.json b/packages/token-distribution/package.json index 93f89d25b..28c891f75 100644 --- a/packages/token-distribution/package.json +++ b/packages/token-distribution/package.json @@ -6,12 +6,17 @@ "main": "index.js", "scripts": { "prepublishOnly": "scripts/prepublish", - "build": "node scripts/build.js", + "build": "npm run build:dep && npm run build:self", + "build:dep": "pnpm --filter @graphprotocol/contracts build", + "build:self": "node scripts/build.js", "build:legacy": "scripts/build", + "extract": "node scripts/extract-graphclient.js", "clean": "rm -rf build/ cache/ dist/ .graphclient/", + "clean:extracted": "rm -rf .graphclient-extracted/", + "clean:all": "rm -rf build/ cache/ dist/ .graphclient/ .graphclient-extracted/", "compile": "hardhat compile --show-stack-traces", "deploy": "pnpm run build && hardhat deploy", - "test": "pnpm build && pnpm --filter @graphprotocol/contracts run build && scripts/test", + "test": "npm run build && scripts/test", "test:gas": "RUN_EVM=true REPORT_GAS=true scripts/test", "test:coverage:broken": "pnpm build && scripts/coverage", "lint": "pnpm lint:ts; pnpm lint:sol; pnpm lint:md; pnpm lint:json", @@ -56,12 +61,12 @@ "coingecko-api": "^1.0.10", "consola": "^2.15.0", "dotenv": "^16.0.0", - "eslint": "^9.28.0", + "eslint": "catalog:", "ethereum-waffle": "^4.0.10", "ethers": "^5.7.0", "graphql": "^16.5.0", "graphql-yoga": "^5.13.4", - "hardhat": "^2.24.0", + "hardhat": "catalog:", "hardhat-abi-exporter": "^2.0.1", "hardhat-contract-sizer": "^2.0.1", "hardhat-deploy": "^0.7.0-beta.9", @@ -70,13 +75,16 @@ "lodash": "^4.17.21", "markdownlint-cli": "0.45.0", "p-queue": "^6.6.2", - "prettier": "^3.5.3", - "prettier-plugin-solidity": "^2.0.0", - "solhint": "^5.1.0", + "prettier": "catalog:", + "prettier-plugin-solidity": "catalog:", + "solhint": "catalog:", "solidity-coverage": "^0.8.16", "ts-node": "^10.9.2", "typechain": "^8.3.0", - "typescript": "^5.8.3", - "typescript-eslint": "^8.33.1" + "typescript": "catalog:", + "typescript-eslint": "catalog:" + }, + "dependencies": { + "ajv": "^8.17.1" } } diff --git a/packages/token-distribution/scripts/build.js b/packages/token-distribution/scripts/build.js index a9a5e1717..bf19da698 100755 --- a/packages/token-distribution/scripts/build.js +++ b/packages/token-distribution/scripts/build.js @@ -93,8 +93,28 @@ async function getDirModTime(dirPath) { } } +// Check if required API keys are available +function hasRequiredApiKeys() { + // Check for Studio API key (required for GraphClient) + const studioApiKey = process.env.STUDIO_API_KEY || process.env.GRAPH_API_KEY + return !!studioApiKey +} + +// Check if extracted GraphClient artifacts exist +function hasExtractedArtifacts() { + const extractedDir = '.graphclient-extracted' + const extractedIndex = path.join(extractedDir, 'index.js') + const extractedTypes = path.join(extractedDir, 'index.d.ts') + return fileExists(extractedIndex) && fileExists(extractedTypes) +} + // Check if GraphClient build is needed async function needsGraphClientBuild() { + // If we have extracted artifacts and no API keys, we don't need a full build + if (!hasRequiredApiKeys() && hasExtractedArtifacts()) { + return false + } + // If GraphClient output doesn't exist, build is needed if (!fileExists(graphClientSchema) || !fileExists(graphClientIndex)) { return true @@ -121,28 +141,49 @@ async function needsContractCompilation() { return contractsSrcTime > artifactsTime } -// Main build function -async function build() { +// Setup GraphClient artifacts for compilation +async function setupGraphClient() { + const hasApiKeys = hasRequiredApiKeys() + const hasExtracted = hasExtractedArtifacts() const graphClientBuildNeeded = await needsGraphClientBuild() - const contractCompilationNeeded = await needsContractCompilation() - // If no build is needed, exit early - if (!graphClientBuildNeeded && !contractCompilationNeeded) { - console.log('All build targets are up to date.') + // If no API keys but we have extracted artifacts, use those instead of trying to build + if (!hasApiKeys && hasExtracted) { + console.log('📦 Using cached GraphClient artifacts (no API key)') + console.warn('⚠️ Schemas might be outdated - set STUDIO_API_KEY or GRAPH_API_KEY to refresh') return } - // Build GraphClient if needed if (graphClientBuildNeeded) { - console.log('Building GraphClient...') - execSync('pnpm graphclient build --fileType json', { stdio: 'inherit' }) + if (hasApiKeys) { + // Stage 1: Download with API key - fail if download fails + console.log('📥 Downloading GraphClient schemas...') + execSync('pnpm graphclient build --fileType json', { stdio: 'inherit' }) + + // Stage 2: Extract essential artifacts for future offline builds + console.log('📦 Extracting essential artifacts...') + execSync('node scripts/extract-graphclient.js', { stdio: 'inherit' }) + } else { + // No API key and no cached artifacts - cannot proceed + // To fix: Set STUDIO_API_KEY or GRAPH_API_KEY environment variable + console.error('❌ No API key or cached GraphClient artifacts available') + process.exit(1) + } } else { - console.log('GraphClient is up to date.') + console.log('📦 GraphClient up to date') } +} + +// Main build function +async function build() { + const contractCompilationNeeded = await needsContractCompilation() + + // Stage 1 & 2: Setup GraphClient (download + extract, or use extracted) + await setupGraphClient() - // Compile contracts if needed + // Stage 3: Compile contracts if needed if (contractCompilationNeeded) { - console.log('Compiling contracts...') + console.log('🔨 Compiling contracts...') // // Copy working TypeChain modules from contracts package to fix compatibility // console.log('Copying TypeChain modules from contracts package...') @@ -155,7 +196,7 @@ async function build() { console.log('Contracts are up to date.') } - console.log('Build completed successfully.') + console.log('✅ Build completed successfully.') } // Run the build diff --git a/packages/token-distribution/scripts/extract-graphclient.js b/packages/token-distribution/scripts/extract-graphclient.js new file mode 100644 index 000000000..771abc74b --- /dev/null +++ b/packages/token-distribution/scripts/extract-graphclient.js @@ -0,0 +1,190 @@ +#!/usr/bin/env node + +/** + * Extract essential GraphClient artifacts for offline builds + * + * This script extracts only the minimal TypeScript types and query documents + * needed for compilation from the full GraphClient build output. + * The extracted files are small and can be committed to git. + */ + +const fs = require('fs') +const path = require('path') + +// Paths +const graphClientDir = '.graphclient' +const extractedDir = '.graphclient-extracted' +const graphClientIndex = path.join(graphClientDir, 'index.js') +const graphClientTypes = path.join(graphClientDir, 'index.d.ts') + +// Helper functions +const fileExists = (filePath) => fs.existsSync(filePath) +const ensureDir = (dirPath) => { + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }) + } +} + +// Create minimal self-contained GraphClient artifacts +function createMinimalArtifacts() { + if (!fileExists(graphClientTypes)) { + throw new Error('GraphClient types not found. Run GraphClient build first.') + } + + // Read the original files + const originalTypes = fs.readFileSync(graphClientTypes, 'utf8') + const originalJs = fs.readFileSync(graphClientIndex, 'utf8') + + // Extract only the specific types we need + const neededTypes = [ + 'TokenLockWallet', + 'GraphNetwork', + 'GraphAccount', + 'Indexer', + 'Curator', + 'Delegator', + 'CuratorWalletsQuery', + 'GraphAccountQuery', + 'GraphNetworkQuery', + 'TokenLockWalletsQuery', + 'Maybe', + 'InputMaybe', + 'Scalars', + ] + + // Extract only the query documents we need + const neededQueries = [ + 'CuratorWalletsDocument', + 'GraphAccountDocument', + 'GraphNetworkDocument', + 'TokenLockWalletsDocument', + ] + + // Create minimal types file + const minimalTypes = extractSpecificTypes(originalTypes, neededTypes) + + // Create minimal JS file + const minimalJs = createMinimalJs(originalJs, neededQueries) + + return { types: minimalTypes, js: minimalJs } +} + +// Extract specific types from the original types file +function extractSpecificTypes(content, neededTypes) { + const lines = content.split('\n') + const result = [] + let currentType = null + let braceDepth = 0 + let inNeededType = false + + // Always include imports and utility types + for (const line of lines) { + if (line.includes('import ') || line.includes('export {')) { + result.push(line) + continue + } + + // Check if this starts a type we need + const typeMatch = line.match(/export (?:type|interface) (\w+)/) + if (typeMatch) { + currentType = typeMatch[1] + if (neededTypes.includes(currentType)) { + inNeededType = true + braceDepth = 0 + result.push(line) + braceDepth += (line.match(/{/g) || []).length + braceDepth -= (line.match(/}/g) || []).length + if (line.trim().endsWith(';') && braceDepth === 0) { + inNeededType = false + } + continue + } else { + inNeededType = false + continue + } + } + + if (inNeededType) { + result.push(line) + braceDepth += (line.match(/{/g) || []).length + braceDepth -= (line.match(/}/g) || []).length + if (braceDepth === 0 && (line.trim().endsWith(';') || line.trim().endsWith('}'))) { + inNeededType = false + } + } + } + + return result.join('\n') +} + +// Create minimal JS with only needed queries +function createMinimalJs(content, neededQueries) { + // Extract only the queries we need + const queryRegex = /exports\.(.*Document)\s*=\s*\(0,\s*utils_1\.gql\)\s*`([\s\S]*?)`\s*;/g + const extractedQueries = [] + let match + + while ((match = queryRegex.exec(content)) !== null) { + const [, docName, query] = match + if (neededQueries.includes(docName)) { + extractedQueries.push(`exports.${docName} = gql\`${query}\`;`) + } + } + + return `"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); + +// Minimal GraphClient for offline builds - contains only what ops/info.ts uses +const { gql } = require('@graphql-mesh/utils'); + +// Mock execute function +const execute = () => { + throw new Error('GraphClient execute() requires API key. This is an offline build with cached types only.'); +}; +exports.execute = execute; + +// Only the query documents actually used +${extractedQueries.join('\n\n')} + +// Mock SDK +function getSdk() { + return { + GraphAccount: () => execute(), + CuratorWallets: () => execute(), + GraphNetwork: () => execute(), + TokenLockWallets: () => execute(), + }; +} +exports.getSdk = getSdk; +` +} + +// The compilation approach handles both types and runtime code together +// No separate query extraction needed + +// Main extract function +async function extract() { + // Ensure extracted directory exists + ensureDir(extractedDir) + + try { + // Create minimal self-contained artifacts (only types/queries used by ops/info.ts) + const artifacts = createMinimalArtifacts() + + // Write the minimal types and runtime code + fs.writeFileSync(path.join(extractedDir, 'index.d.ts'), artifacts.types) + fs.writeFileSync(path.join(extractedDir, 'index.js'), artifacts.js) + + console.log(`✅ Extracted minimal artifacts to ${extractedDir}/`) + } catch (error) { + console.error('❌ Extraction failed:', error.message) + process.exit(1) + } +} + +// Run if called directly +if (require.main === module) { + extract() +} + +module.exports = { extract } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index af3b1831c..190c9f403 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,42 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +catalogs: + default: + '@eslint/js': + specifier: ^9.28.0 + version: 9.28.0 + eslint: + specifier: ^9.28.0 + version: 9.28.0 + eslint-config-prettier: + specifier: ^10.1.5 + version: 10.1.5 + hardhat: + specifier: ^2.24.0 + version: 2.24.2 + hardhat-contract-sizer: + specifier: ^2.10.0 + version: 2.10.0 + hardhat-gas-reporter: + specifier: ^1.0.8 + version: 1.0.10 + hardhat-secure-accounts: + specifier: ^1.0.5 + version: 1.0.5 + hardhat-storage-layout: + specifier: ^0.1.7 + version: 0.1.7 + markdownlint-cli: + specifier: ^0.45.0 + version: 0.45.0 + solhint: + specifier: ^6.0.0 + version: 6.0.0 + typescript-eslint: + specifier: ^8.33.1 + version: 8.33.1 + overrides: prettier: ^3.5.3 prettier-plugin-solidity: ^2.0.0 @@ -12,7 +48,7 @@ overrides: patchedDependencies: typechain@8.3.2: - hash: zy6bsbkpcar7tt6jjbnwpaczsm + hash: b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6 path: patches/typechain@8.3.2.patch importers: @@ -24,25 +60,16 @@ importers: version: 2.29.4 '@commitlint/cli': specifier: 19.8.1 - version: 19.8.1(@types/node@20.17.58)(typescript@5.8.3) + version: 19.8.1(@types/node@20.19.9)(typescript@5.8.3) '@commitlint/config-conventional': specifier: 19.8.1 version: 19.8.1 - '@defi-wonderland/natspec-smells': - specifier: ^1.1.6 - version: 1.1.6(typescript@5.8.3)(zod@3.25.51) '@eslint/eslintrc': specifier: ^3.3.1 version: 3.3.1 '@eslint/js': specifier: ^9.28.0 version: 9.28.0 - '@openzeppelin/contracts': - specifier: ^5.3.0 - version: 5.3.0 - '@openzeppelin/contracts-upgradeable': - specifier: ^5.3.0 - version: 5.3.0(@openzeppelin/contracts@5.3.0) '@typescript-eslint/eslint-plugin': specifier: ^8.33.1 version: 8.33.1(@typescript-eslint/parser@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) @@ -95,8 +122,8 @@ importers: specifier: ^4.1.1 version: 4.2.2(prettier@3.5.3) solhint: - specifier: ^5.1.0 - version: 5.1.0(typescript@5.8.3) + specifier: 'catalog:' + version: 6.0.0(typescript@5.8.3) typescript: specifier: ^5.8.3 version: 5.8.3 @@ -113,41 +140,38 @@ importers: specifier: ^16.3.1 version: 16.5.0 devDependencies: - '@defi-wonderland/natspec-smells': - specifier: ^1.1.6 - version: 1.1.6(typescript@5.8.3)(zod@3.25.51) + '@openzeppelin/contracts': + specifier: ^5.3.0 + version: 5.3.0 + '@openzeppelin/contracts-upgradeable': + specifier: ^5.3.0 + version: 5.3.0(@openzeppelin/contracts@5.3.0) '@types/node': specifier: ^20.17.50 version: 20.17.58 eslint: - specifier: ^9.28.0 + specifier: 'catalog:' version: 9.28.0(jiti@2.4.2) eslint-config-prettier: - specifier: ^10.1.5 + specifier: 'catalog:' version: 10.1.5(eslint@9.28.0(jiti@2.4.2)) globals: specifier: ^16.1.0 version: 16.1.0 - hardhat: - specifier: ^2.24.0 - version: 2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) markdownlint-cli: - specifier: ^0.45.0 + specifier: 'catalog:' version: 0.45.0 prettier: specifier: ^3.5.3 version: 3.5.3 - prettier-plugin-solidity: - specifier: ^2.0.0 - version: 2.0.0(prettier@3.5.3) solhint: - specifier: 5.1.0 - version: 5.1.0(typescript@5.8.3) + specifier: 'catalog:' + version: 6.0.0(typescript@5.8.3) typescript: specifier: ^5.8.3 version: 5.8.3 typescript-eslint: - specifier: ^8.33.1 + specifier: 'catalog:' version: 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) packages/contracts: @@ -202,10 +226,10 @@ importers: version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(@nomiclabs/hardhat-etherscan@3.1.8(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(encoding@0.1.13)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) '@typechain/ethers-v5': specifier: ^10.2.1 - version: 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3) + version: 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3) '@typechain/hardhat': specifier: ^6.1.2 - version: 6.1.6(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3)) + version: 6.1.6(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3)) '@types/chai': specifier: ^4.2.0 version: 4.3.20 @@ -228,7 +252,7 @@ importers: specifier: ^16.5.0 version: 16.5.0 eslint: - specifier: ^9.28.0 + specifier: 'catalog:' version: 9.28.0(jiti@2.4.2) ethereum-waffle: specifier: ^4.0.10 @@ -249,22 +273,22 @@ importers: specifier: ^2.12.4 version: 2.12.6(graphql@16.11.0) hardhat: - specifier: ^2.24.0 + specifier: 'catalog:' version: 2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) hardhat-abi-exporter: specifier: ^2.11.0 version: 2.11.0(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) hardhat-contract-sizer: - specifier: ^2.10.0 + specifier: 'catalog:' version: 2.10.0(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) hardhat-gas-reporter: - specifier: ^1.0.8 + specifier: 'catalog:' version: 1.0.10(bufferutil@4.0.9)(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) hardhat-secure-accounts: - specifier: 0.0.6 - version: 0.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + specifier: 'catalog:' + version: 1.0.5(@nomicfoundation/hardhat-ethers@3.0.9(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) hardhat-storage-layout: - specifier: ^0.1.7 + specifier: 'catalog:' version: 0.1.7(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) prettier: specifier: ^3.5.3 @@ -273,8 +297,8 @@ importers: specifier: ^2.0.0 version: 2.0.0(prettier@3.5.3) solhint: - specifier: ^5.1.0 - version: 5.1.0(typescript@5.8.3) + specifier: 'catalog:' + version: 6.0.0(typescript@5.8.3) solidity-coverage: specifier: ^0.8.16 version: 0.8.16(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) @@ -283,7 +307,7 @@ importers: version: 10.9.2(@types/node@20.17.58)(typescript@5.8.3) typechain: specifier: ^8.3.2 - version: 8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3) + version: 8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3) typescript: specifier: ^5.8.3 version: 5.8.3 @@ -356,10 +380,10 @@ importers: version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(@nomiclabs/hardhat-etherscan@3.1.8(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(encoding@0.1.13)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) '@typechain/ethers-v5': specifier: ^10.2.1 - version: 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3) + version: 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3) '@typechain/hardhat': specifier: ^6.1.2 - version: 6.1.6(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3)) + version: 6.1.6(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3)) '@types/glob': specifier: ^8.1.0 version: 8.1.0 @@ -414,15 +438,12 @@ importers: prettier-plugin-solidity: specifier: ^2.0.0 version: 2.0.0(prettier@3.5.3) - solhint: - specifier: ^5.1.0 - version: 5.1.0(typescript@5.8.3) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@20.17.58)(typescript@5.8.3) typechain: specifier: ^8.3.2 - version: 8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3) + version: 8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3) typescript: specifier: ^5.8.3 version: 5.8.3 @@ -498,10 +519,10 @@ importers: version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(@nomiclabs/hardhat-etherscan@3.1.8(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(encoding@0.1.13)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) '@typechain/ethers-v5': specifier: ^10.2.1 - version: 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3) + version: 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3) '@typechain/hardhat': specifier: ^6.1.2 - version: 6.1.6(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3)) + version: 6.1.6(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3)) '@types/chai': specifier: ^4.2.0 version: 4.3.20 @@ -553,9 +574,6 @@ importers: hardhat-contract-sizer: specifier: ^2.10.0 version: 2.10.0(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - hardhat-dependency-compiler: - specifier: ^1.2.1 - version: 1.2.1(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) hardhat-gas-reporter: specifier: ^1.0.8 version: 1.0.10(bufferutil@4.0.9)(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) @@ -571,9 +589,6 @@ importers: prettier-plugin-solidity: specifier: ^2.0.0 version: 2.0.0(prettier@3.5.3) - solhint: - specifier: ^5.1.0 - version: 5.1.0(typescript@5.8.3) solidity-coverage: specifier: ^0.8.16 version: 0.8.16(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) @@ -582,7 +597,7 @@ importers: version: 10.9.2(@types/node@20.17.58)(typescript@5.8.3) typechain: specifier: ^8.3.2 - version: 8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3) + version: 8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3) typescript: specifier: ^5.8.3 version: 5.8.3 @@ -636,10 +651,10 @@ importers: version: 1.11.0(@types/node@20.17.58)(bufferutil@4.0.9)(encoding@0.1.13)(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) '@typechain/ethers-v5': specifier: ^10.2.1 - version: 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3) + version: 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3) '@typechain/hardhat': specifier: ^6.1.6 - version: 6.1.6(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3)) + version: 6.1.6(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3)) '@types/mocha': specifier: ^9.0.0 version: 9.1.1 @@ -656,7 +671,7 @@ importers: specifier: ^16.0.0 version: 16.5.0 eslint: - specifier: ^9.28.0 + specifier: 'catalog:' version: 9.28.0(jiti@2.4.2) ethereum-waffle: specifier: ^3.0.2 @@ -668,7 +683,7 @@ importers: specifier: ^1.2.5 version: 1.2.5(solium@1.2.5) hardhat: - specifier: ^2.24.0 + specifier: 'catalog:' version: 2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) hardhat-abi-exporter: specifier: ^2.2.0 @@ -701,8 +716,8 @@ importers: specifier: ^2.0.0 version: 2.0.0(prettier@3.5.3) solhint: - specifier: ^5.1.0 - version: 5.1.0(typescript@5.8.3) + specifier: 'catalog:' + version: 6.0.0(typescript@5.8.3) solidity-coverage: specifier: ^0.8.16 version: 0.8.16(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) @@ -714,7 +729,7 @@ importers: version: 10.9.2(@types/node@20.17.58)(typescript@5.8.3) typechain: specifier: ^8.3.0 - version: 8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3) + version: 8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3) typescript: specifier: ^5.8.3 version: 5.8.3 @@ -752,7 +767,7 @@ importers: specifier: ^5.7.0 version: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) hardhat: - specifier: ^2.24.0 + specifier: 'catalog:' version: 2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) hardhat-secure-accounts: specifier: 0.0.6 @@ -768,7 +783,7 @@ importers: version: 1.10.2 devDependencies: '@eslint/js': - specifier: ^9.28.0 + specifier: 'catalog:' version: 9.28.0 '@types/chai': specifier: ^4.3.9 @@ -798,7 +813,7 @@ importers: specifier: ^7.1.1 version: 7.1.2(chai@4.5.0) eslint: - specifier: ^9.28.0 + specifier: 'catalog:' version: 9.28.0(jiti@2.4.2) globals: specifier: 16.1.0 @@ -806,17 +821,24 @@ importers: markdownlint-cli: specifier: 0.45.0 version: 0.45.0 + mocha: + specifier: ^11.7.1 + version: 11.7.1 prettier: specifier: ^3.5.3 version: 3.5.3 ts-node: - specifier: ^10.9.1 + specifier: ^10.9.2 version: 10.9.2(@types/node@20.17.58)(typescript@5.8.3) typescript: specifier: ^5.8.3 version: 5.8.3 packages/token-distribution: + dependencies: + ajv: + specifier: ^8.17.1 + version: 8.17.1 devDependencies: '@ethersproject/abi': specifier: ^5.7.0 @@ -835,7 +857,7 @@ importers: version: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@graphprotocol/client-cli': specifier: ^2.2.22 - version: 2.2.22(@babel/core@7.27.4)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/store@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(@graphql-tools/merge@9.0.24(graphql@16.11.0))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@graphql-tools/wrap@9.4.2(graphql@16.11.0))(@types/node@20.17.58)(bufferutil@4.0.9)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + version: 2.2.22(@babel/core@7.27.4)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(@graphql-tools/merge@9.0.24(graphql@16.11.0))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@graphql-tools/wrap@9.4.2(graphql@16.11.0))(@types/node@20.17.58)(bufferutil@4.0.9)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) '@graphprotocol/contracts': specifier: workspace:^ version: link:../contracts @@ -862,10 +884,10 @@ importers: version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(@nomiclabs/hardhat-etherscan@3.1.8(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(encoding@0.1.13)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) '@typechain/ethers-v5': specifier: ^10.2.1 - version: 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3) + version: 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3) '@typechain/hardhat': specifier: ^6.1.6 - version: 6.1.6(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3)) + version: 6.1.6(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3)) '@types/mocha': specifier: ^9.1.0 version: 9.1.1 @@ -888,7 +910,7 @@ importers: specifier: ^16.0.0 version: 16.5.0 eslint: - specifier: ^9.28.0 + specifier: 'catalog:' version: 9.28.0(jiti@2.4.2) ethereum-waffle: specifier: ^4.0.10 @@ -903,7 +925,7 @@ importers: specifier: ^5.13.4 version: 5.13.5(graphql@16.11.0) hardhat: - specifier: ^2.24.0 + specifier: 'catalog:' version: 2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) hardhat-abi-exporter: specifier: ^2.0.1 @@ -936,8 +958,8 @@ importers: specifier: ^2.0.0 version: 2.0.0(prettier@3.5.3) solhint: - specifier: ^5.1.0 - version: 5.1.0(typescript@5.8.3) + specifier: 'catalog:' + version: 6.0.0(typescript@5.8.3) solidity-coverage: specifier: ^0.8.16 version: 0.8.16(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) @@ -946,12 +968,12 @@ importers: version: 10.9.2(@types/node@20.17.58)(typescript@5.8.3) typechain: specifier: ^8.3.0 - version: 8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3) + version: 8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3) typescript: specifier: ^5.8.3 version: 5.8.3 typescript-eslint: - specifier: ^8.33.1 + specifier: 'catalog:' version: 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) packages: @@ -1009,6 +1031,10 @@ packages: resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==} engines: {node: '>=6.9.0'} + '@babel/generator@7.28.0': + resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==} + engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@7.27.3': resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} engines: {node: '>=6.9.0'} @@ -1023,6 +1049,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + '@babel/helper-member-expression-to-functions@7.27.1': resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==} engines: {node: '>=6.9.0'} @@ -1076,6 +1106,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.28.0': + resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-proposal-class-properties@7.18.6': resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} engines: {node: '>=6.9.0'} @@ -1311,6 +1346,10 @@ packages: resolution: {integrity: sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.28.2': + resolution: {integrity: sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==} + engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} @@ -1319,10 +1358,18 @@ packages: resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.28.0': + resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==} + engines: {node: '>=6.9.0'} + '@babel/types@7.27.6': resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} engines: {node: '>=6.9.0'} + '@babel/types@7.28.2': + resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==} + engines: {node: '>=6.9.0'} + '@bytecodealliance/preview2-shim@0.17.0': resolution: {integrity: sha512-JorcEwe4ud0x5BS/Ar2aQWOQoFzjq/7jcnxYXCvSMh0oRm0dQXzOA+hqLDBnOMks1LLBA7dmiLLsEBl09Yd6iQ==} @@ -1537,10 +1584,6 @@ packages: '@dabh/diagnostics@2.0.3': resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} - '@defi-wonderland/natspec-smells@1.1.6': - resolution: {integrity: sha512-HTdZLEdBs3UakW0JQZ7vO8pb6YCoU3CPQNfLxa0Z9PWAwmgKhSZJbF8dm/okkJEJGRa0dCoOxviJw5jeK+kDiQ==} - hasBin: true - '@defi-wonderland/smock@2.4.1': resolution: {integrity: sha512-SvWg0joZppEWEB1XopkJazH1+whLw48KgwYLblml0Y7meJLK+J33uuPNtEsmAwgXWCCt6CouK2fXtSEDz2zKVw==} deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. @@ -2468,6 +2511,10 @@ packages: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} + '@humanwhocodes/momoa@2.0.4': + resolution: {integrity: sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==} + engines: {node: '>=10.10.0'} + '@humanwhocodes/retry@0.3.1': resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} engines: {node: '>=18.18'} @@ -2516,6 +2563,9 @@ packages: resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jridgewell/gen-mapping@0.3.12': + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} + '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} @@ -2528,15 +2578,21 @@ packages: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - '@jridgewell/source-map@0.3.6': - resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + '@jridgewell/source-map@0.3.10': + resolution: {integrity: sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==} '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/sourcemap-codec@1.5.4': + resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} + '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.29': + resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} + '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} @@ -2668,6 +2724,12 @@ packages: c-kzg: optional: true + '@nomicfoundation/hardhat-ethers@3.0.9': + resolution: {integrity: sha512-xBJdRUiCwKpr0OYrOzPwAyNGtsVzoBx32HFPJVv6S+sFA9TmBIBDaqNlFPmBH58ZjgNnGhEr/4oBZvGr4q4TjQ==} + peerDependencies: + ethers: ^6.14.0 + hardhat: ^2.0.0 + '@nomicfoundation/hardhat-network-helpers@1.0.12': resolution: {integrity: sha512-xTNQNI/9xkHvjmCJnJOTyqDSl8uq1rKb2WOVmixQxFtRd7Oa3ecO8zM0cyC2YmOK+jHB9WPZ+F/ijkHg1CoORA==} peerDependencies: @@ -3060,8 +3122,8 @@ packages: '@types/babel__template@7.4.4': resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - '@types/babel__traverse@7.20.7': - resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} '@types/bn.js@4.11.6': resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} @@ -3168,6 +3230,9 @@ packages: '@types/node@20.17.58': resolution: {integrity: sha512-UvxetCgGwZ9HmsgGZ2tpStt6CiFU1bu28ftHWpDyfthsCt7OHXas0C7j0VgO3gBq8UHKI785wXmtcQVhLekcRg==} + '@types/node@20.19.9': + resolution: {integrity: sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==} + '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -3356,15 +3421,6 @@ packages: abbrev@1.0.9: resolution: {integrity: sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==} - abitype@0.7.1: - resolution: {integrity: sha512-VBkRHTDZf9Myaek/dO3yMmOzB/y2s3Zo6nVU7yaw1G+TvCHAjwaJzNGN9yo4K5D8bU/VZXKP1EJpRhFr862PlQ==} - peerDependencies: - typescript: ^5.8.3 - zod: ^3 >=3.19.1 - peerDependenciesMeta: - zod: - optional: true - abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -3415,6 +3471,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + adm-zip@0.4.16: resolution: {integrity: sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==} engines: {node: '>=0.3.0'} @@ -3437,6 +3498,11 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} + ajv-errors@1.0.1: + resolution: {integrity: sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==} + peerDependencies: + ajv: '>=5.0.0' + ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -3902,10 +3968,10 @@ packages: babel-plugin-transform-strict-mode@6.24.1: resolution: {integrity: sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw==} - babel-preset-current-node-syntax@1.1.0: - resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + babel-preset-current-node-syntax@1.2.0: + resolution: {integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==} peerDependencies: - '@babel/core': ^7.0.0 + '@babel/core': ^7.0.0 || ^8.0.0-0 babel-preset-env@1.7.0: resolution: {integrity: sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==} @@ -3976,6 +4042,12 @@ packages: bech32@1.1.4: resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} + better-ajv-errors@2.0.2: + resolution: {integrity: sha512-1cLrJXEq46n0hjV8dDYwg9LKYjDb3KbeW7nZTv4kvfoDD9c2DXHIE31nxM+Y/cIfXMggLUfmxbm6h/JoM/yotA==} + engines: {node: '>= 18.20.6'} + peerDependencies: + ajv: 4.11.8 - 8 + better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} @@ -4833,9 +4905,6 @@ packages: resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} engines: {node: '>=10'} - decimal.js@10.5.0: - resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} - decode-named-character-reference@1.1.0: resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==} @@ -4956,10 +5025,6 @@ packages: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - detect-file@1.0.0: - resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} - engines: {node: '>=0.10.0'} - detect-indent@4.0.0: resolution: {integrity: sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A==} engines: {node: '>=0.10.0'} @@ -4992,6 +5057,10 @@ packages: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} + diff@7.0.0: + resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} + engines: {node: '>=0.3.1'} + diffie-hellman@5.0.3: resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} @@ -5549,10 +5618,6 @@ packages: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} - expand-tilde@2.0.2: - resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} - engines: {node: '>=0.10.0'} - exponential-backoff@3.1.2: resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==} @@ -5623,10 +5688,6 @@ packages: fast-diff@1.3.0: resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} @@ -5756,10 +5817,6 @@ packages: find-yarn-workspace-root@2.0.0: resolution: {integrity: sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==} - findup-sync@5.0.0: - resolution: {integrity: sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==} - engines: {node: '>= 10.13.0'} - flat-cache@4.0.1: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} @@ -5783,6 +5840,15 @@ packages: fn.name@1.1.0: resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + follow-redirects@1.15.9: resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} @@ -6074,18 +6140,10 @@ packages: resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==} engines: {node: '>=4'} - global-modules@1.0.0: - resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==} - engines: {node: '>=0.10.0'} - global-modules@2.0.0: resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} engines: {node: '>=6'} - global-prefix@1.0.2: - resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} - engines: {node: '>=0.10.0'} - global-prefix@3.0.0: resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} engines: {node: '>=6'} @@ -6225,12 +6283,6 @@ packages: peerDependencies: hardhat: ^2.0.0 - hardhat-dependency-compiler@1.2.1: - resolution: {integrity: sha512-xG5iwbspTtxOEiP5UsPngEYQ1Hg+fjTjliapIjdTQmwGkCPofrsDhQDV2O/dopcYzcR68nTx2X8xTewYHgA2rQ==} - engines: {node: '>=14.14.0'} - peerDependencies: - hardhat: ^2.0.0 - hardhat-deploy@0.11.45: resolution: {integrity: sha512-aC8UNaq3JcORnEUIwV945iJuvBwi65tjHVDU3v6mOcqik7WAzHVCJ7cwmkkipsHrWysrB5YvGF1q9S1vIph83w==} @@ -6252,6 +6304,13 @@ packages: ethers: ^5.0.0 hardhat: ^2.0.0 + hardhat-secure-accounts@1.0.5: + resolution: {integrity: sha512-gr0bV1eh1sOOSy2CgQ0BMFwQ8QPLBLBB7mJIT4VYNkEf6+fPjO8r70lNapoX53zMhfy9kQe7F0ko6yKpkcBqBg==} + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^3.0.0 + ethers: ^6.13.0 + hardhat: ^2.22.0 + hardhat-storage-layout@0.1.7: resolution: {integrity: sha512-q723g2iQnJpRdMC6Y8fbh/stG6MLHKNxa5jq/ohjtD5znOlOzQ6ojYuInY8V4o4WcPyG3ty4hzHYunLf66/1+A==} peerDependencies: @@ -6377,14 +6436,14 @@ packages: hermes-estree@0.25.1: resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} - hermes-estree@0.28.1: - resolution: {integrity: sha512-w3nxl/RGM7LBae0v8LH2o36+8VqwOZGv9rX1wyoWT6YaKZLqpJZ0YQ5P0LVr3tuRpf7vCx0iIG4i/VmBJejxTQ==} + hermes-estree@0.29.1: + resolution: {integrity: sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==} hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hermes-parser@0.28.1: - resolution: {integrity: sha512-nf8o+hE8g7UJWParnccljHumE9Vlq8F7MqIdeahl+4x0tvCUJYRrT0L7h0MMg/X9YJmkNwsfbaNNrzPtFXOscg==} + hermes-parser@0.29.1: + resolution: {integrity: sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==} hmac-drbg@1.0.1: resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} @@ -6393,10 +6452,6 @@ packages: resolution: {integrity: sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg==} engines: {node: '>=0.10.0'} - homedir-polyfill@1.0.3: - resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} - engines: {node: '>=0.10.0'} - hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -7062,10 +7117,6 @@ packages: resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==} engines: {node: '>=12.0.0'} - jsel@1.1.6: - resolution: {integrity: sha512-7E6r8kVzjmKhwXR/82Z+43edfOJGRvLvx6cJZ+SS2MGAPPtYZGnaIsFHpQMA1IbIPA9twDProkob4IIAJ0ZqSw==} - engines: {node: '>=0.10.0'} - jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true @@ -7690,61 +7741,61 @@ packages: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - metro-babel-transformer@0.82.4: - resolution: {integrity: sha512-4juJahGRb1gmNbQq48lNinB6WFNfb6m0BQqi/RQibEltNiqTCxew/dBspI2EWA4xVCd3mQWGfw0TML4KurQZnQ==} + metro-babel-transformer@0.82.5: + resolution: {integrity: sha512-W/scFDnwJXSccJYnOFdGiYr9srhbHPdxX9TvvACOFsIXdLilh3XuxQl/wXW6jEJfgIb0jTvoTlwwrqvuwymr6Q==} engines: {node: '>=18.18'} - metro-cache-key@0.82.4: - resolution: {integrity: sha512-2JCTqcpF+f2OghOpe/+x+JywfzDkrHdAqinPFWmK2ezNAU/qX0jBFaTETogPibFivxZJil37w9Yp6syX8rFUng==} + metro-cache-key@0.82.5: + resolution: {integrity: sha512-qpVmPbDJuRLrT4kcGlUouyqLGssJnbTllVtvIgXfR7ZuzMKf0mGS+8WzcqzNK8+kCyakombQWR0uDd8qhWGJcA==} engines: {node: '>=18.18'} - metro-cache@0.82.4: - resolution: {integrity: sha512-vX0ylSMGtORKiZ4G8uP6fgfPdDiCWvLZUGZ5zIblSGylOX6JYhvExl0Zg4UA9pix/SSQu5Pnp9vdODMFsNIxhw==} + metro-cache@0.82.5: + resolution: {integrity: sha512-AwHV9607xZpedu1NQcjUkua8v7HfOTKfftl6Vc9OGr/jbpiJX6Gpy8E/V9jo/U9UuVYX2PqSUcVNZmu+LTm71Q==} engines: {node: '>=18.18'} - metro-config@0.82.4: - resolution: {integrity: sha512-Ki3Wumr3hKHGDS7RrHsygmmRNc/PCJrvkLn0+BWWxmbOmOcMMJDSmSI+WRlT8jd5VPZFxIi4wg+sAt5yBXAK0g==} + metro-config@0.82.5: + resolution: {integrity: sha512-/r83VqE55l0WsBf8IhNmc/3z71y2zIPe5kRSuqA5tY/SL/ULzlHUJEMd1szztd0G45JozLwjvrhAzhDPJ/Qo/g==} engines: {node: '>=18.18'} - metro-core@0.82.4: - resolution: {integrity: sha512-Xo4ozbxPg2vfgJGCgXZ8sVhC2M0lhTqD+tsKO2q9aelq/dCjnnSb26xZKcQO80CQOQUL7e3QWB7pLFGPjZm31A==} + metro-core@0.82.5: + resolution: {integrity: sha512-OJL18VbSw2RgtBm1f2P3J5kb892LCVJqMvslXxuxjAPex8OH7Eb8RBfgEo7VZSjgb/LOf4jhC4UFk5l5tAOHHA==} engines: {node: '>=18.18'} - metro-file-map@0.82.4: - resolution: {integrity: sha512-eO7HD1O3aeNsbEe6NBZvx1lLJUrxgyATjnDmb7bm4eyF6yWOQot9XVtxTDLNifECuvsZ4jzRiTInrbmIHkTdGA==} + metro-file-map@0.82.5: + resolution: {integrity: sha512-vpMDxkGIB+MTN8Af5hvSAanc6zXQipsAUO+XUx3PCQieKUfLwdoa8qaZ1WAQYRpaU+CJ8vhBcxtzzo3d9IsCIQ==} engines: {node: '>=18.18'} - metro-minify-terser@0.82.4: - resolution: {integrity: sha512-W79Mi6BUwWVaM8Mc5XepcqkG+TSsCyyo//dmTsgYfJcsmReQorRFodil3bbJInETvjzdnS1mCsUo9pllNjT1Hg==} + metro-minify-terser@0.82.5: + resolution: {integrity: sha512-v6Nx7A4We6PqPu/ta1oGTqJ4Usz0P7c+3XNeBxW9kp8zayS3lHUKR0sY0wsCHInxZlNAEICx791x+uXytFUuwg==} engines: {node: '>=18.18'} - metro-resolver@0.82.4: - resolution: {integrity: sha512-uWoHzOBGQTPT5PjippB8rRT3iI9CTgFA9tRiLMzrseA5o7YAlgvfTdY9vFk2qyk3lW3aQfFKWkmqENryPRpu+Q==} + metro-resolver@0.82.5: + resolution: {integrity: sha512-kFowLnWACt3bEsuVsaRNgwplT8U7kETnaFHaZePlARz4Fg8tZtmRDUmjaD68CGAwc0rwdwNCkWizLYpnyVcs2g==} engines: {node: '>=18.18'} - metro-runtime@0.82.4: - resolution: {integrity: sha512-vVyFO7H+eLXRV2E7YAUYA7aMGBECGagqxmFvC2hmErS7oq90BbPVENfAHbUWq1vWH+MRiivoRxdxlN8gBoF/dw==} + metro-runtime@0.82.5: + resolution: {integrity: sha512-rQZDoCUf7k4Broyw3Ixxlq5ieIPiR1ULONdpcYpbJQ6yQ5GGEyYjtkztGD+OhHlw81LCR2SUAoPvtTus2WDK5g==} engines: {node: '>=18.18'} - metro-source-map@0.82.4: - resolution: {integrity: sha512-9jzDQJ0FPas1FuQFtwmBHsez2BfhFNufMowbOMeG3ZaFvzeziE8A0aJwILDS3U+V5039ssCQFiQeqDgENWvquA==} + metro-source-map@0.82.5: + resolution: {integrity: sha512-wH+awTOQJVkbhn2SKyaw+0cd+RVSCZ3sHVgyqJFQXIee/yLs3dZqKjjeKKhhVeudgjXo7aE/vSu/zVfcQEcUfw==} engines: {node: '>=18.18'} - metro-symbolicate@0.82.4: - resolution: {integrity: sha512-LwEwAtdsx7z8rYjxjpLWxuFa2U0J6TS6ljlQM4WAATKa4uzV8unmnRuN2iNBWTmRqgNR77mzmI2vhwD4QSCo+w==} + metro-symbolicate@0.82.5: + resolution: {integrity: sha512-1u+07gzrvYDJ/oNXuOG1EXSvXZka/0JSW1q2EYBWerVKMOhvv9JzDGyzmuV7hHbF2Hg3T3S2uiM36sLz1qKsiw==} engines: {node: '>=18.18'} hasBin: true - metro-transform-plugins@0.82.4: - resolution: {integrity: sha512-NoWQRPHupVpnDgYguiEcm7YwDhnqW02iWWQjO2O8NsNP09rEMSq99nPjARWfukN7+KDh6YjLvTIN20mj3dk9kw==} + metro-transform-plugins@0.82.5: + resolution: {integrity: sha512-57Bqf3rgq9nPqLrT2d9kf/2WVieTFqsQ6qWHpEng5naIUtc/Iiw9+0bfLLWSAw0GH40iJ4yMjFcFJDtNSYynMA==} engines: {node: '>=18.18'} - metro-transform-worker@0.82.4: - resolution: {integrity: sha512-kPI7Ad/tdAnI9PY4T+2H0cdgGeSWWdiPRKuytI806UcN4VhFL6OmYa19/4abYVYF+Cd2jo57CDuwbaxRfmXDhw==} + metro-transform-worker@0.82.5: + resolution: {integrity: sha512-mx0grhAX7xe+XUQH6qoHHlWedI8fhSpDGsfga7CpkO9Lk9W+aPitNtJWNGrW8PfjKEWbT9Uz9O50dkI8bJqigw==} engines: {node: '>=18.18'} - metro@0.82.4: - resolution: {integrity: sha512-/gFmw3ux9CPG5WUmygY35hpyno28zi/7OUn6+OFfbweA8l0B+PPqXXLr0/T6cf5nclCcH0d22o+02fICaShVxw==} + metro@0.82.5: + resolution: {integrity: sha512-8oAXxL7do8QckID/WZEKaIFuQJFUTLzfVcC48ghkHhNK2RGuQq8Xvf4AVd+TUA0SZtX0q8TGNXZ/eba1ckeGCg==} engines: {node: '>=18.18'} hasBin: true @@ -8011,6 +8062,11 @@ packages: engines: {node: '>= 14.0.0'} hasBin: true + mocha@11.7.1: + resolution: {integrity: sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + mocha@4.1.0: resolution: {integrity: sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==} engines: {node: '>= 4.0.0'} @@ -8251,8 +8307,8 @@ packages: oauth-sign@0.9.0: resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} - ob1@0.82.4: - resolution: {integrity: sha512-n9S8e4l5TvkrequEAMDidl4yXesruWTNTzVkeaHSGywoTOIwTzZzKw7Z670H3eaXDZui5MJXjWGNzYowVZIxCA==} + ob1@0.82.5: + resolution: {integrity: sha512-QyQQ6e66f+Ut/qUVjEce0E/wux5nAGLXYZDn1jr15JWstHsCH3l6VVrg8NKDptW9NEiBXKOJeGF/ydxeSDF3IQ==} engines: {node: '>=18.18'} object-assign@4.1.1: @@ -8528,10 +8584,6 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} - parse-passwd@1.0.0: - resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} - engines: {node: '>=0.10.0'} - parse-statements@1.0.11: resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==} @@ -9035,8 +9087,8 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - react-devtools-core@6.1.2: - resolution: {integrity: sha512-ldFwzufLletzCikNJVYaxlxMLu7swJ3T2VrGfzXlMsVhZhPDKXA38DEROidaYZVgMAmQnIjymrmqto5pyfrwPA==} + react-devtools-core@6.1.5: + resolution: {integrity: sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==} react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} @@ -9235,10 +9287,6 @@ packages: resolve-alpn@1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} - resolve-dir@1.0.1: - resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} - engines: {node: '>=0.10.0'} - resolve-from@3.0.0: resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} engines: {node: '>=4'} @@ -9722,10 +9770,6 @@ packages: sol-explore@1.6.1: resolution: {integrity: sha512-cmwg7l+QLj2LE3Qvwrdo4aPYcNYY425+bN5VPkgCjkO0CiSz33G5vM5BmMZNrfd/6yNGwcm0KtwDJmh5lUElEQ==} - solc-typed-ast@18.2.4: - resolution: {integrity: sha512-HTkr6b2WMSJ3pgVRf5us/UWjCvfSlvE1yUcHna+miSPerkyppGnZQaJWqrcECa7ZjxmSV7H2buUDKux9hR4ivg==} - hasBin: true - solc@0.4.26: resolution: {integrity: sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA==} hasBin: true @@ -9740,18 +9784,13 @@ packages: engines: {node: '>=10.0.0'} hasBin: true - solc@0.8.25: - resolution: {integrity: sha512-7P0TF8gPeudl1Ko3RGkyY6XVCxe2SdD/qQhtns1vl3yAbK/PDifKDLHGtx1t7mX3LgR7ojV7Fg/Kc6Q9D2T8UQ==} - engines: {node: '>=10.0.0'} - hasBin: true - solc@0.8.26: resolution: {integrity: sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==} engines: {node: '>=10.0.0'} hasBin: true - solhint@5.1.0: - resolution: {integrity: sha512-KWg4gnOnznxHXzH0fUvnhnxnk+1R50GiPChcPeQgA7SKQTSF1LLIEh8R1qbkCEn/fFzz4CfJs+Gh7Rl9uhHy+g==} + solhint@6.0.0: + resolution: {integrity: sha512-PQGfwFqfeYdebi2tEG1fhVfMjqSzbW3Noz+LYf8UusKe5nkikCghdgEjYQPcGfFZj4snlVyJQt//AaxkubOtVQ==} hasBin: true solidity-ast@0.4.60: @@ -9846,9 +9885,6 @@ packages: sprintf-js@1.1.3: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - src-location@1.1.0: - resolution: {integrity: sha512-idBVZgLZGzB3B2Et317AFDQto7yRgp1tOuFd+VKIH2dw1jO1b6p07zNjtQoVhkW+CY6oGTp9Y5UIfbJoZRsoFQ==} - sshpk@1.18.0: resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} engines: {node: '>=0.10.0'} @@ -10081,8 +10117,8 @@ packages: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} - terser@5.41.0: - resolution: {integrity: sha512-H406eLPXpZbAX14+B8psIuvIr8+3c+2hkuYzpMkoE0ij+NdsVATbA78vb8neA/eqrj7rywa2pIkdmWRsXW6wmw==} + terser@5.43.1: + resolution: {integrity: sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==} engines: {node: '>=10'} hasBin: true @@ -10448,6 +10484,9 @@ packages: undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici@5.29.0: resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} engines: {node: '>=14.0'} @@ -10560,9 +10599,6 @@ packages: resolution: {integrity: sha512-GIEaZ6o86fj09Wtf0VfZ5XP7tmd4t3jM5aZCgmBi231D0DB1AEBa3Aa6MP48DMsAIi96WkpWLimIWVwOjbDMOw==} engines: {node: '>= 0.8'} - util@0.12.5: - resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} - utils-merge@1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} @@ -10648,18 +10684,10 @@ packages: resolution: {integrity: sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ==} engines: {node: '>=8.0.0'} - web3-errors@1.3.1: - resolution: {integrity: sha512-w3NMJujH+ZSW4ltIZZKtdbkbyQEvBzyp3JRn59Ckli0Nz4VMsVq8aF1bLWM7A2kuQ+yVEm3ySeNU+7mSRwx7RQ==} - engines: {node: '>=14', npm: '>=6.12.0'} - web3-eth-abi@1.2.11: resolution: {integrity: sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg==} engines: {node: '>=8.0.0'} - web3-eth-abi@4.4.1: - resolution: {integrity: sha512-60ecEkF6kQ9zAfbTY04Nc9q4eEYM0++BySpGi8wZ2PD1tw/c0SDvsKhV6IKURxLJhsDlb08dATc3iD6IbtWJmg==} - engines: {node: '>=14', npm: '>=6.12.0'} - web3-eth-accounts@1.2.11: resolution: {integrity: sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw==} engines: {node: '>=8.0.0'} @@ -10708,10 +10736,6 @@ packages: resolution: {integrity: sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg==} engines: {node: '>=8.0.0'} - web3-types@1.10.0: - resolution: {integrity: sha512-0IXoaAFtFc8Yin7cCdQfB9ZmjafrbP6BO0f0KT/khMhXKUpoJ6yShrVhiNpyRBo8QQjuOagsWzwSK2H49I7sbw==} - engines: {node: '>=14', npm: '>=6.12.0'} - web3-utils@1.10.4: resolution: {integrity: sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==} engines: {node: '>=8.0.0'} @@ -10720,14 +10744,6 @@ packages: resolution: {integrity: sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ==} engines: {node: '>=8.0.0'} - web3-utils@4.3.3: - resolution: {integrity: sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==} - engines: {node: '>=14', npm: '>=6.12.0'} - - web3-validator@2.0.6: - resolution: {integrity: sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==} - engines: {node: '>=14', npm: '>=6.12.0'} - web3@1.2.11: resolution: {integrity: sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ==} engines: {node: '>=8.0.0'} @@ -10829,6 +10845,9 @@ packages: workerpool@6.5.1: resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==} + workerpool@9.3.3: + resolution: {integrity: sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==} + wrap-ansi@2.1.0: resolution: {integrity: sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==} engines: {node: '>=0.10.0'} @@ -10937,6 +10956,18 @@ packages: utf-8-validate: optional: true + ws@8.18.2: + resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xhr-request-promise@0.1.3: resolution: {integrity: sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==} @@ -11173,6 +11204,14 @@ snapshots: '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 + '@babel/generator@7.28.0': + dependencies: + '@babel/parser': 7.28.0 + '@babel/types': 7.28.2 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + jsesc: 3.1.0 + '@babel/helper-annotate-as-pure@7.27.3': dependencies: '@babel/types': 7.27.6 @@ -11198,6 +11237,8 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-globals@7.28.0': {} + '@babel/helper-member-expression-to-functions@7.27.1': dependencies: '@babel/traverse': 7.27.4 @@ -11258,6 +11299,10 @@ snapshots: dependencies: '@babel/types': 7.27.6 + '@babel/parser@7.28.0': + dependencies: + '@babel/types': 7.28.2 + '@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 @@ -11498,6 +11543,8 @@ snapshots: '@babel/runtime@7.27.6': {} + '@babel/runtime@7.28.2': {} + '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 @@ -11516,11 +11563,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.28.0': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/types': 7.28.2 + debug: 4.4.1(supports-color@9.4.0) + transitivePeerDependencies: + - supports-color + '@babel/types@7.27.6': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 + '@babel/types@7.28.2': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@bytecodealliance/preview2-shim@0.17.0': {} '@bytecodealliance/preview2-shim@0.17.2': {} @@ -11687,11 +11751,11 @@ snapshots: - '@swc/core' - '@swc/wasm' - '@commitlint/cli@19.8.1(@types/node@20.17.58)(typescript@5.8.3)': + '@commitlint/cli@19.8.1(@types/node@20.19.9)(typescript@5.8.3)': dependencies: '@commitlint/format': 19.8.1 '@commitlint/lint': 19.8.1 - '@commitlint/load': 19.8.1(@types/node@20.17.58)(typescript@5.8.3) + '@commitlint/load': 19.8.1(@types/node@20.19.9)(typescript@5.8.3) '@commitlint/read': 19.8.1 '@commitlint/types': 19.8.1 tinyexec: 1.0.1 @@ -11788,7 +11852,7 @@ snapshots: - '@swc/core' - '@swc/wasm' - '@commitlint/load@19.8.1(@types/node@20.17.58)(typescript@5.8.3)': + '@commitlint/load@19.8.1(@types/node@20.19.9)(typescript@5.8.3)': dependencies: '@commitlint/config-validator': 19.8.1 '@commitlint/execute-rule': 19.8.1 @@ -11796,7 +11860,7 @@ snapshots: '@commitlint/types': 19.8.1 chalk: 5.4.1 cosmiconfig: 9.0.0(typescript@5.8.3) - cosmiconfig-typescript-loader: 6.1.0(@types/node@20.17.58)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3) + cosmiconfig-typescript-loader: 6.1.0(@types/node@20.19.9)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -11899,16 +11963,6 @@ snapshots: enabled: 2.0.0 kuler: 2.0.0 - '@defi-wonderland/natspec-smells@1.1.6(typescript@5.8.3)(zod@3.25.51)': - dependencies: - fast-glob: 3.3.2 - solc-typed-ast: 18.2.4(typescript@5.8.3)(zod@3.25.51) - yargs: 17.7.2 - transitivePeerDependencies: - - debug - - typescript - - zod - '@defi-wonderland/smock@2.4.1(@ethersproject/abi@5.8.0)(@ethersproject/abstract-provider@5.8.0)(@ethersproject/abstract-signer@5.8.0)(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))': dependencies: '@ethersproject/abi': 5.8.0 @@ -12070,18 +12124,18 @@ snapshots: - typescript - utf-8-validate - '@ethereum-waffle/compiler@4.0.3(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(encoding@0.1.13)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solc@0.8.15)(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3)': + '@ethereum-waffle/compiler@4.0.3(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(encoding@0.1.13)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solc@0.8.15)(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3)': dependencies: '@resolver-engine/imports': 0.3.3 '@resolver-engine/imports-fs': 0.3.3 - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3) + '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3) '@types/mkdirp': 0.5.2 '@types/node-fetch': 2.6.12 ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) mkdirp: 0.5.6 node-fetch: 2.7.0(encoding@0.1.13) solc: 0.8.15 - typechain: 8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3) + typechain: 8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3) transitivePeerDependencies: - '@ethersproject/abi' - '@ethersproject/providers' @@ -13072,7 +13126,7 @@ snapshots: optionalDependencies: '@trufflesuite/bigint-buffer': 1.1.9 - '@graphprotocol/client-add-source-name@1.0.20(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@graphql-tools/wrap@9.4.2(graphql@16.11.0))(graphql@16.11.0)': + '@graphprotocol/client-add-source-name@1.0.20(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@graphql-tools/wrap@9.4.2(graphql@16.11.0))(graphql@16.11.0)': dependencies: '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-tools/delegate': 9.0.35(graphql@16.11.0) @@ -13082,7 +13136,7 @@ snapshots: lodash: 4.17.21 tslib: 2.8.1 - '@graphprotocol/client-auto-pagination@1.1.18(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@graphql-tools/wrap@9.4.2(graphql@16.11.0))(graphql@16.11.0)': + '@graphprotocol/client-auto-pagination@1.1.18(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@graphql-tools/wrap@9.4.2(graphql@16.11.0))(graphql@16.11.0)': dependencies: '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-tools/delegate': 9.0.35(graphql@16.11.0) @@ -13092,9 +13146,9 @@ snapshots: lodash: 4.17.21 tslib: 2.8.1 - '@graphprotocol/client-auto-type-merging@1.0.25(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(graphql@16.11.0)': + '@graphprotocol/client-auto-type-merging@1.0.25(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(graphql@16.11.0)': dependencies: - '@graphql-mesh/transform-type-merging': 0.93.1(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(graphql@16.11.0)(tslib@2.8.1) + '@graphql-mesh/transform-type-merging': 0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-tools/delegate': 9.0.35(graphql@16.11.0) graphql: 16.11.0 @@ -13109,15 +13163,15 @@ snapshots: graphql: 16.11.0 tslib: 2.8.1 - ? '@graphprotocol/client-cli@2.2.22(@babel/core@7.27.4)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/store@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(@graphql-tools/merge@9.0.24(graphql@16.11.0))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@graphql-tools/wrap@9.4.2(graphql@16.11.0))(@types/node@20.17.58)(bufferutil@4.0.9)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10)' - : dependencies: - '@graphprotocol/client-add-source-name': 1.0.20(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@graphql-tools/wrap@9.4.2(graphql@16.11.0))(graphql@16.11.0) - '@graphprotocol/client-auto-pagination': 1.1.18(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@graphql-tools/wrap@9.4.2(graphql@16.11.0))(graphql@16.11.0) - '@graphprotocol/client-auto-type-merging': 1.0.25(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(graphql@16.11.0) + '@graphprotocol/client-cli@2.2.22(@babel/core@7.27.4)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(@graphql-tools/merge@9.0.24(graphql@16.11.0))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@graphql-tools/wrap@9.4.2(graphql@16.11.0))(@types/node@20.17.58)(bufferutil@4.0.9)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10)': + dependencies: + '@graphprotocol/client-add-source-name': 1.0.20(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@graphql-tools/wrap@9.4.2(graphql@16.11.0))(graphql@16.11.0) + '@graphprotocol/client-auto-pagination': 1.1.18(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@graphql-tools/wrap@9.4.2(graphql@16.11.0))(graphql@16.11.0) + '@graphprotocol/client-auto-type-merging': 1.0.25(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(graphql@16.11.0) '@graphprotocol/client-block-tracking': 1.0.14(@graphql-tools/delegate@9.0.35(graphql@16.11.0))(graphql@16.11.0) '@graphprotocol/client-polling-live': 1.1.1(@envelop/core@3.0.6)(@graphql-tools/merge@9.0.24(graphql@16.11.0))(graphql@16.11.0) '@graphql-mesh/cli': 0.82.35(@babel/core@7.27.4)(@types/node@20.17.58)(bufferutil@4.0.9)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) - '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/store@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@types/node@20.17.58)(bufferutil@4.0.9)(encoding@0.1.13)(graphql@16.11.0)(tslib@2.8.1)(utf-8-validate@5.0.10) + '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@types/node@20.17.58)(bufferutil@4.0.9)(encoding@0.1.13)(graphql@16.11.0)(tslib@2.8.1)(utf-8-validate@5.0.10) graphql: 16.11.0 tslib: 2.8.1 transitivePeerDependencies: @@ -13395,7 +13449,7 @@ snapshots: object-inspect: 1.10.3 tslib: 2.8.1 - '@graphql-mesh/cache-localforage@0.93.1(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(graphql@16.11.0)(tslib@2.8.1)': + '@graphql-mesh/cache-localforage@0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.11.0)(tslib@2.8.1)': dependencies: '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) @@ -13411,10 +13465,10 @@ snapshots: '@graphql-codegen/typescript-generic-sdk': 3.1.0(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.11.0))(graphql@16.11.0) '@graphql-codegen/typescript-operations': 3.0.4(encoding@0.1.13)(graphql@16.11.0) '@graphql-codegen/typescript-resolvers': 3.2.1(encoding@0.1.13)(graphql@16.11.0) - '@graphql-mesh/config': 0.93.1(@babel/core@7.27.4)(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/runtime@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/store@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) + '@graphql-mesh/config': 0.93.1(@babel/core@7.27.4)(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/runtime@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)) - '@graphql-mesh/http': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/runtime@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(graphql@16.11.0)(tslib@2.8.1) - '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) + '@graphql-mesh/http': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/runtime@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.11.0)(tslib@2.8.1) + '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) @@ -13437,7 +13491,7 @@ snapshots: tsconfig-paths: 4.2.0 tslib: 2.8.1 typescript: 5.8.3 - ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) yargs: 17.7.2 transitivePeerDependencies: - '@babel/core' @@ -13452,14 +13506,14 @@ snapshots: - supports-color - utf-8-validate - ? '@graphql-mesh/config@0.93.1(@babel/core@7.27.4)(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/runtime@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/store@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1)' - : dependencies: + '@graphql-mesh/config@0.93.1(@babel/core@7.27.4)(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/runtime@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1)': + dependencies: '@envelop/core': 3.0.6 - '@graphql-mesh/cache-localforage': 0.93.1(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(graphql@16.11.0)(tslib@2.8.1) + '@graphql-mesh/cache-localforage': 0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)) - '@graphql-mesh/merger-bare': 0.93.1(@graphql-mesh/store@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) - '@graphql-mesh/merger-stitching': 0.93.1(@graphql-mesh/store@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) - '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) + '@graphql-mesh/merger-bare': 0.93.1(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) + '@graphql-mesh/merger-stitching': 0.93.1(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) + '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) @@ -13488,8 +13542,8 @@ snapshots: - react-native - react-native-windows - ? '@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/store@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@types/node@20.17.58)(bufferutil@4.0.9)(encoding@0.1.13)(graphql@16.11.0)(tslib@2.8.1)(utf-8-validate@5.0.10)' - : dependencies: + '@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(@types/node@20.17.58)(bufferutil@4.0.9)(encoding@0.1.13)(graphql@16.11.0)(tslib@2.8.1)(utf-8-validate@5.0.10)': + dependencies: '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)) '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.11.0)(tslib@2.8.1) @@ -13508,10 +13562,10 @@ snapshots: - encoding - utf-8-validate - ? '@graphql-mesh/http@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/runtime@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(graphql@16.11.0)(tslib@2.8.1)' - : dependencies: + '@graphql-mesh/http@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/runtime@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.11.0)(tslib@2.8.1)': + dependencies: '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)) - '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) + '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) fets: 0.1.5 @@ -13519,9 +13573,9 @@ snapshots: graphql-yoga: 3.9.1(graphql@16.11.0) tslib: 2.8.1 - '@graphql-mesh/merger-bare@0.93.1(@graphql-mesh/store@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1)': + '@graphql-mesh/merger-bare@0.93.1(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1)': dependencies: - '@graphql-mesh/merger-stitching': 0.93.1(@graphql-mesh/store@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) + '@graphql-mesh/merger-stitching': 0.93.1(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-tools/schema': 9.0.19(graphql@16.11.0) @@ -13531,7 +13585,7 @@ snapshots: transitivePeerDependencies: - '@graphql-mesh/store' - '@graphql-mesh/merger-stitching@0.93.1(@graphql-mesh/store@0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1)': + '@graphql-mesh/merger-stitching@0.93.1(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1)': dependencies: '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) @@ -13544,7 +13598,7 @@ snapshots: graphql: 16.11.0 tslib: 2.8.1 - '@graphql-mesh/runtime@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1)': + '@graphql-mesh/runtime@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1)': dependencies: '@envelop/core': 3.0.6 '@envelop/extended-validation': 2.0.6(@envelop/core@3.0.6)(graphql@16.11.0) @@ -13579,7 +13633,7 @@ snapshots: lodash.get: 4.4.2 tslib: 2.8.1 - '@graphql-mesh/transform-type-merging@0.93.1(@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1))(graphql@16.11.0)(tslib@2.8.1)': + '@graphql-mesh/transform-type-merging@0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.11.0)(tslib@2.8.1)': dependencies: '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(react-native@0.79.3(@babel/core@7.27.4)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1(graphql@16.11.0))(graphql@16.11.0)(tslib@2.8.1) @@ -13832,10 +13886,10 @@ snapshots: '@types/ws': 8.18.1 '@whatwg-node/fetch': 0.8.8 graphql: 16.11.0 - isomorphic-ws: 5.0.0(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + isomorphic-ws: 5.0.0(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) tslib: 2.8.1 value-or-promise: 1.0.12 - ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) transitivePeerDependencies: - '@types/node' - bufferutil @@ -13926,6 +13980,8 @@ snapshots: '@humanwhocodes/module-importer@1.0.1': {} + '@humanwhocodes/momoa@2.0.4': {} + '@humanwhocodes/retry@0.3.1': {} '@humanwhocodes/retry@0.4.3': {} @@ -13959,14 +14015,14 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.17.58 + '@types/node': 20.19.9 jest-mock: 29.7.0 '@jest/fake-timers@29.7.0': dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.17.58 + '@types/node': 20.19.9 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -13979,7 +14035,7 @@ snapshots: dependencies: '@babel/core': 7.27.4 '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/trace-mapping': 0.3.29 babel-plugin-istanbul: 6.1.1 chalk: 4.1.2 convert-source-map: 2.0.0 @@ -14000,10 +14056,15 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.17.58 + '@types/node': 20.19.9 '@types/yargs': 17.0.33 chalk: 4.1.2 + '@jridgewell/gen-mapping@0.3.12': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping': 0.3.29 + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 @@ -14014,18 +14075,25 @@ snapshots: '@jridgewell/set-array@1.2.1': {} - '@jridgewell/source-map@0.3.6': + '@jridgewell/source-map@0.3.10': dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/sourcemap-codec@1.5.4': {} + '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.29': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 @@ -14180,6 +14248,15 @@ snapshots: '@nomicfoundation/ethereumjs-rlp': 5.0.4 ethereum-cryptography: 0.1.3 + '@nomicfoundation/hardhat-ethers@3.0.9(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))': + dependencies: + debug: 4.4.1(supports-color@9.4.0) + ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + hardhat: 2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + lodash.isequal: 4.5.0 + transitivePeerDependencies: + - supports-color + '@nomicfoundation/hardhat-network-helpers@1.0.12(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))': dependencies: ethereumjs-util: 7.1.5 @@ -14395,9 +14472,9 @@ snapshots: chalk: 4.1.2 debug: 2.6.9 invariant: 2.2.4 - metro: 0.82.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) - metro-config: 0.82.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) - metro-core: 0.82.4 + metro: 0.82.5(bufferutil@4.0.9)(utf-8-validate@5.0.10) + metro-config: 0.82.5(bufferutil@4.0.9)(utf-8-validate@5.0.10) + metro-core: 0.82.5 semver: 7.7.2 transitivePeerDependencies: - bufferutil @@ -14696,14 +14773,14 @@ snapshots: '@tsconfig/node16@1.0.4': {} - '@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3)': + '@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3)': dependencies: '@ethersproject/abi': 5.8.0 '@ethersproject/providers': 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) lodash: 4.17.21 ts-essentials: 7.0.3(typescript@5.8.3) - typechain: 8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3) + typechain: 8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3) typescript: 5.8.3 '@typechain/ethers-v5@2.0.0(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@3.0.0(typescript@5.8.3))': @@ -14711,38 +14788,38 @@ snapshots: ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) typechain: 3.0.0(typescript@5.8.3) - '@typechain/hardhat@6.1.6(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))': + '@typechain/hardhat@6.1.6(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))': dependencies: '@ethersproject/abi': 5.8.0 '@ethersproject/providers': 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3) + '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3) ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) fs-extra: 9.1.0 hardhat: 2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) - typechain: 8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3) + typechain: 8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3) '@types/abstract-leveldown@7.2.5': {} '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.27.5 - '@babel/types': 7.27.6 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.2 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.7 + '@types/babel__traverse': 7.28.0 '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.27.6 + '@babel/types': 7.28.2 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.27.5 - '@babel/types': 7.27.6 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.2 - '@types/babel__traverse@7.20.7': + '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.27.6 + '@babel/types': 7.28.2 '@types/bn.js@4.11.6': dependencies: @@ -14796,7 +14873,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.17.58 + '@types/node': 20.19.9 '@types/http-cache-semantics@4.0.4': {} @@ -14865,6 +14942,10 @@ snapshots: dependencies: undici-types: 6.19.8 + '@types/node@20.19.9': + dependencies: + undici-types: 6.21.0 + '@types/normalize-package-data@2.4.4': {} '@types/parse-json@4.0.2': {} @@ -15110,12 +15191,6 @@ snapshots: abbrev@1.0.9: {} - abitype@0.7.1(typescript@5.8.3)(zod@3.25.51): - dependencies: - typescript: 5.8.3 - optionalDependencies: - zod: 3.25.51 - abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -15167,6 +15242,8 @@ snapshots: acorn@8.14.1: {} + acorn@8.15.0: {} + adm-zip@0.4.16: {} aes-js@3.0.0: {} @@ -15187,6 +15264,10 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 + ajv-errors@1.0.1(ajv@6.12.6): + dependencies: + ajv: 6.12.6 + ajv-formats@2.1.1(ajv@8.17.1): optionalDependencies: ajv: 8.17.1 @@ -15671,9 +15752,9 @@ snapshots: babel-plugin-jest-hoist@29.6.3: dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.27.6 + '@babel/types': 7.28.2 '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.7 + '@types/babel__traverse': 7.28.0 babel-plugin-syntax-async-functions@6.13.0: {} @@ -15856,7 +15937,7 @@ snapshots: babel-runtime: 6.26.0 babel-types: 6.26.0 - babel-preset-current-node-syntax@1.1.0(@babel/core@7.27.4): + babel-preset-current-node-syntax@1.2.0(@babel/core@7.27.4): dependencies: '@babel/core': 7.27.4 '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.27.4) @@ -15947,7 +16028,7 @@ snapshots: dependencies: '@babel/core': 7.27.4 babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.27.4) + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.27.4) babel-register@6.26.0: dependencies: @@ -16042,6 +16123,15 @@ snapshots: bech32@1.1.4: {} + better-ajv-errors@2.0.2(ajv@6.12.6): + dependencies: + '@babel/code-frame': 7.27.1 + '@humanwhocodes/momoa': 2.0.4 + ajv: 6.12.6 + chalk: 4.1.2 + jsonpointer: 5.0.1 + leven: 3.1.0 + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 @@ -16623,7 +16713,7 @@ snapshots: chrome-launcher@0.15.2: dependencies: - '@types/node': 20.17.58 + '@types/node': 20.19.9 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -16632,7 +16722,7 @@ snapshots: chromium-edge-launcher@0.2.0: dependencies: - '@types/node': 20.17.58 + '@types/node': 20.19.9 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -16972,9 +17062,9 @@ snapshots: - '@swc/core' - '@swc/wasm' - cosmiconfig-typescript-loader@6.1.0(@types/node@20.17.58)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3): + cosmiconfig-typescript-loader@6.1.0(@types/node@20.19.9)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3): dependencies: - '@types/node': 20.17.58 + '@types/node': 20.19.9 cosmiconfig: 9.0.0(typescript@5.8.3) jiti: 2.4.2 typescript: 5.8.3 @@ -17177,8 +17267,6 @@ snapshots: decamelize@4.0.0: {} - decimal.js@10.5.0: {} - decode-named-character-reference@1.1.0: dependencies: character-entities: 2.0.2 @@ -17294,8 +17382,6 @@ snapshots: destroy@1.2.0: {} - detect-file@1.0.0: {} - detect-indent@4.0.0: dependencies: repeating: 2.0.1 @@ -17317,6 +17403,8 @@ snapshots: diff@5.2.0: {} + diff@7.0.0: {} + diffie-hellman@5.0.3: dependencies: bn.js: 4.12.2 @@ -17948,12 +18036,12 @@ snapshots: ethereum-waffle@4.0.10(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(encoding@0.1.13)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typescript@5.8.3): dependencies: '@ethereum-waffle/chai': 4.0.10(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@ethereum-waffle/compiler': 4.0.3(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(encoding@0.1.13)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solc@0.8.15)(typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3))(typescript@5.8.3) + '@ethereum-waffle/compiler': 4.0.3(@ethersproject/abi@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(encoding@0.1.13)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solc@0.8.15)(typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3))(typescript@5.8.3) '@ethereum-waffle/mock-contract': 4.0.4(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@ethereum-waffle/provider': 4.0.5(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) solc: 0.8.15 - typechain: 8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3) + typechain: 8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3) transitivePeerDependencies: - '@ensdomains/ens' - '@ensdomains/resolver' @@ -18321,10 +18409,6 @@ snapshots: expand-template@2.0.3: optional: true - expand-tilde@2.0.2: - dependencies: - homedir-polyfill: 1.0.3 - exponential-backoff@3.1.2: {} express@4.17.3: @@ -18493,14 +18577,6 @@ snapshots: fast-diff@1.3.0: {} - fast-glob@3.3.2: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -18688,13 +18764,6 @@ snapshots: dependencies: micromatch: 4.0.8 - findup-sync@5.0.0: - dependencies: - detect-file: 1.0.0 - is-glob: 4.0.3 - micromatch: 4.0.8 - resolve-dir: 1.0.1 - flat-cache@4.0.1: dependencies: flatted: 3.3.3 @@ -18714,6 +18783,10 @@ snapshots: fn.name@1.1.0: {} + follow-redirects@1.15.11(debug@4.4.1): + optionalDependencies: + debug: 4.4.1(supports-color@9.4.0) + follow-redirects@1.15.9(debug@4.4.1): optionalDependencies: debug: 4.4.1(supports-color@9.4.0) @@ -19088,24 +19161,10 @@ snapshots: dependencies: ini: 1.3.8 - global-modules@1.0.0: - dependencies: - global-prefix: 1.0.2 - is-windows: 1.0.2 - resolve-dir: 1.0.1 - global-modules@2.0.0: dependencies: global-prefix: 3.0.0 - global-prefix@1.0.2: - dependencies: - expand-tilde: 2.0.2 - homedir-polyfill: 1.0.3 - ini: 1.3.8 - is-windows: 1.0.2 - which: 1.3.1 - global-prefix@3.0.0: dependencies: ini: 1.3.8 @@ -19303,10 +19362,6 @@ snapshots: hardhat: 2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) strip-ansi: 6.0.1 - hardhat-dependency-compiler@1.2.1(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)): - dependencies: - hardhat: 2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) - hardhat-deploy@0.11.45(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: '@ethersproject/abi': 5.8.0 @@ -19391,6 +19446,18 @@ snapshots: transitivePeerDependencies: - supports-color + hardhat-secure-accounts@1.0.5(@nomicfoundation/hardhat-ethers@3.0.9(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)): + dependencies: + '@nomicfoundation/hardhat-ethers': 3.0.9(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + debug: 4.4.1(supports-color@9.4.0) + enquirer: 2.4.1 + ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + hardhat: 2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + lodash.clonedeep: 4.5.0 + prompt-sync: 4.2.0 + transitivePeerDependencies: + - supports-color + hardhat-storage-layout@0.1.7(hardhat@2.24.2(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@20.17.58)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)): dependencies: console-table-printer: 2.14.1 @@ -19541,15 +19608,15 @@ snapshots: hermes-estree@0.25.1: {} - hermes-estree@0.28.1: {} + hermes-estree@0.29.1: {} hermes-parser@0.25.1: dependencies: hermes-estree: 0.25.1 - hermes-parser@0.28.1: + hermes-parser@0.29.1: dependencies: - hermes-estree: 0.28.1 + hermes-estree: 0.29.1 hmac-drbg@1.0.1: dependencies: @@ -19562,10 +19629,6 @@ snapshots: os-homedir: 1.0.2 os-tmpdir: 1.0.2 - homedir-polyfill@1.0.3: - dependencies: - parse-passwd: 1.0.0 - hosted-git-info@2.8.9: {} hosted-git-info@4.1.0: @@ -20087,9 +20150,9 @@ snapshots: dependencies: ws: 8.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - isomorphic-ws@5.0.0(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)): + isomorphic-ws@5.0.0(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)): dependencies: - ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) isstream@0.1.2: {} @@ -20098,7 +20161,7 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: '@babel/core': 7.27.4 - '@babel/parser': 7.27.5 + '@babel/parser': 7.28.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -20120,7 +20183,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.17.58 + '@types/node': 20.19.9 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -20130,7 +20193,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.17.58 + '@types/node': 20.19.9 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -20157,7 +20220,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.17.58 + '@types/node': 20.19.9 jest-util: 29.7.0 jest-regex-util@29.6.3: {} @@ -20165,7 +20228,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.17.58 + '@types/node': 20.19.9 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -20182,7 +20245,7 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 20.17.58 + '@types/node': 20.19.9 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -20218,8 +20281,6 @@ snapshots: jsdoc-type-pratt-parser@4.1.0: {} - jsel@1.1.6: {} - jsesc@0.5.0: {} jsesc@1.3.0: {} @@ -20952,50 +21013,50 @@ snapshots: methods@1.1.2: {} - metro-babel-transformer@0.82.4: + metro-babel-transformer@0.82.5: dependencies: '@babel/core': 7.27.4 flow-enums-runtime: 0.0.6 - hermes-parser: 0.28.1 + hermes-parser: 0.29.1 nullthrows: 1.1.1 transitivePeerDependencies: - supports-color - metro-cache-key@0.82.4: + metro-cache-key@0.82.5: dependencies: flow-enums-runtime: 0.0.6 - metro-cache@0.82.4: + metro-cache@0.82.5: dependencies: exponential-backoff: 3.1.2 flow-enums-runtime: 0.0.6 https-proxy-agent: 7.0.6 - metro-core: 0.82.4 + metro-core: 0.82.5 transitivePeerDependencies: - supports-color - metro-config@0.82.4(bufferutil@4.0.9)(utf-8-validate@5.0.10): + metro-config@0.82.5(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: connect: 3.7.0 cosmiconfig: 5.2.1 flow-enums-runtime: 0.0.6 jest-validate: 29.7.0 - metro: 0.82.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) - metro-cache: 0.82.4 - metro-core: 0.82.4 - metro-runtime: 0.82.4 + metro: 0.82.5(bufferutil@4.0.9)(utf-8-validate@5.0.10) + metro-cache: 0.82.5 + metro-core: 0.82.5 + metro-runtime: 0.82.5 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - metro-core@0.82.4: + metro-core@0.82.5: dependencies: flow-enums-runtime: 0.0.6 lodash.throttle: 4.1.1 - metro-resolver: 0.82.4 + metro-resolver: 0.82.5 - metro-file-map@0.82.4: + metro-file-map@0.82.5: dependencies: debug: 4.4.1(supports-color@9.4.0) fb-watchman: 2.0.2 @@ -21009,86 +21070,86 @@ snapshots: transitivePeerDependencies: - supports-color - metro-minify-terser@0.82.4: + metro-minify-terser@0.82.5: dependencies: flow-enums-runtime: 0.0.6 - terser: 5.41.0 + terser: 5.43.1 - metro-resolver@0.82.4: + metro-resolver@0.82.5: dependencies: flow-enums-runtime: 0.0.6 - metro-runtime@0.82.4: + metro-runtime@0.82.5: dependencies: - '@babel/runtime': 7.27.6 + '@babel/runtime': 7.28.2 flow-enums-runtime: 0.0.6 - metro-source-map@0.82.4: + metro-source-map@0.82.5: dependencies: - '@babel/traverse': 7.27.4 - '@babel/traverse--for-generate-function-map': '@babel/traverse@7.27.4' - '@babel/types': 7.27.6 + '@babel/traverse': 7.28.0 + '@babel/traverse--for-generate-function-map': '@babel/traverse@7.28.0' + '@babel/types': 7.28.2 flow-enums-runtime: 0.0.6 invariant: 2.2.4 - metro-symbolicate: 0.82.4 + metro-symbolicate: 0.82.5 nullthrows: 1.1.1 - ob1: 0.82.4 + ob1: 0.82.5 source-map: 0.5.7 vlq: 1.0.1 transitivePeerDependencies: - supports-color - metro-symbolicate@0.82.4: + metro-symbolicate@0.82.5: dependencies: flow-enums-runtime: 0.0.6 invariant: 2.2.4 - metro-source-map: 0.82.4 + metro-source-map: 0.82.5 nullthrows: 1.1.1 source-map: 0.5.7 vlq: 1.0.1 transitivePeerDependencies: - supports-color - metro-transform-plugins@0.82.4: + metro-transform-plugins@0.82.5: dependencies: '@babel/core': 7.27.4 - '@babel/generator': 7.27.5 + '@babel/generator': 7.28.0 '@babel/template': 7.27.2 - '@babel/traverse': 7.27.4 + '@babel/traverse': 7.28.0 flow-enums-runtime: 0.0.6 nullthrows: 1.1.1 transitivePeerDependencies: - supports-color - metro-transform-worker@0.82.4(bufferutil@4.0.9)(utf-8-validate@5.0.10): + metro-transform-worker@0.82.5(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: '@babel/core': 7.27.4 - '@babel/generator': 7.27.5 - '@babel/parser': 7.27.5 - '@babel/types': 7.27.6 + '@babel/generator': 7.28.0 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.2 flow-enums-runtime: 0.0.6 - metro: 0.82.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) - metro-babel-transformer: 0.82.4 - metro-cache: 0.82.4 - metro-cache-key: 0.82.4 - metro-minify-terser: 0.82.4 - metro-source-map: 0.82.4 - metro-transform-plugins: 0.82.4 + metro: 0.82.5(bufferutil@4.0.9)(utf-8-validate@5.0.10) + metro-babel-transformer: 0.82.5 + metro-cache: 0.82.5 + metro-cache-key: 0.82.5 + metro-minify-terser: 0.82.5 + metro-source-map: 0.82.5 + metro-transform-plugins: 0.82.5 nullthrows: 1.1.1 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - metro@0.82.4(bufferutil@4.0.9)(utf-8-validate@5.0.10): + metro@0.82.5(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: '@babel/code-frame': 7.27.1 '@babel/core': 7.27.4 - '@babel/generator': 7.27.5 - '@babel/parser': 7.27.5 + '@babel/generator': 7.28.0 + '@babel/parser': 7.28.0 '@babel/template': 7.27.2 - '@babel/traverse': 7.27.4 - '@babel/types': 7.27.6 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.2 accepts: 1.3.8 chalk: 4.1.2 ci-info: 2.0.0 @@ -21097,24 +21158,24 @@ snapshots: error-stack-parser: 2.1.4 flow-enums-runtime: 0.0.6 graceful-fs: 4.2.11 - hermes-parser: 0.28.1 + hermes-parser: 0.29.1 image-size: 1.2.1 invariant: 2.2.4 jest-worker: 29.7.0 jsc-safe-url: 0.2.4 lodash.throttle: 4.1.1 - metro-babel-transformer: 0.82.4 - metro-cache: 0.82.4 - metro-cache-key: 0.82.4 - metro-config: 0.82.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) - metro-core: 0.82.4 - metro-file-map: 0.82.4 - metro-resolver: 0.82.4 - metro-runtime: 0.82.4 - metro-source-map: 0.82.4 - metro-symbolicate: 0.82.4 - metro-transform-plugins: 0.82.4 - metro-transform-worker: 0.82.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + metro-babel-transformer: 0.82.5 + metro-cache: 0.82.5 + metro-cache-key: 0.82.5 + metro-config: 0.82.5(bufferutil@4.0.9)(utf-8-validate@5.0.10) + metro-core: 0.82.5 + metro-file-map: 0.82.5 + metro-resolver: 0.82.5 + metro-runtime: 0.82.5 + metro-source-map: 0.82.5 + metro-symbolicate: 0.82.5 + metro-transform-plugins: 0.82.5 + metro-transform-worker: 0.82.5(bufferutil@4.0.9)(utf-8-validate@5.0.10) mime-types: 2.1.35 nullthrows: 1.1.1 serialize-error: 2.1.0 @@ -21522,6 +21583,29 @@ snapshots: yargs-parser: 20.2.9 yargs-unparser: 2.0.0 + mocha@11.7.1: + dependencies: + browser-stdout: 1.3.1 + chokidar: 4.0.3 + debug: 4.4.1(supports-color@8.1.1) + diff: 7.0.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 10.4.5 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 9.0.5 + ms: 2.1.3 + picocolors: 1.1.1 + serialize-javascript: 6.0.2 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 9.3.3 + yargs: 17.7.2 + yargs-parser: 21.1.1 + yargs-unparser: 2.0.0 + mocha@4.1.0: dependencies: browser-stdout: 1.3.0 @@ -21804,7 +21888,7 @@ snapshots: oauth-sign@0.9.0: {} - ob1@0.82.4: + ob1@0.82.5: dependencies: flow-enums-runtime: 0.0.6 @@ -22126,8 +22210,6 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - parse-passwd@1.0.0: {} - parse-statements@1.0.11: {} parseurl@1.3.3: {} @@ -22658,7 +22740,7 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - react-devtools-core@6.1.2(bufferutil@4.0.9)(utf-8-validate@5.0.10): + react-devtools-core@6.1.5(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: shell-quote: 1.8.3 ws: 7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10) @@ -22700,13 +22782,13 @@ snapshots: invariant: 2.2.4 jest-environment-node: 29.7.0 memoize-one: 5.2.1 - metro-runtime: 0.82.4 - metro-source-map: 0.82.4 + metro-runtime: 0.82.5 + metro-source-map: 0.82.5 nullthrows: 1.1.1 pretty-format: 29.7.0 promise: 8.3.0 react: 19.1.0 - react-devtools-core: 6.1.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) + react-devtools-core: 6.1.5(bufferutil@4.0.9)(utf-8-validate@5.0.10) react-refresh: 0.14.2 regenerator-runtime: 0.13.11 scheduler: 0.25.0 @@ -22940,11 +23022,6 @@ snapshots: resolve-alpn@1.2.1: {} - resolve-dir@1.0.1: - dependencies: - expand-tilde: 2.0.2 - global-modules: 1.0.0 - resolve-from@3.0.0: {} resolve-from@4.0.0: {} @@ -23501,23 +23578,6 @@ snapshots: sol-explore@1.6.1: {} - solc-typed-ast@18.2.4(typescript@5.8.3)(zod@3.25.51): - dependencies: - axios: 1.9.0(debug@4.4.1) - commander: 12.1.0 - decimal.js: 10.5.0 - findup-sync: 5.0.0 - fs-extra: 11.3.0 - jsel: 1.1.6 - semver: 7.7.2 - solc: 0.8.25 - src-location: 1.1.0 - web3-eth-abi: 4.4.1(typescript@5.8.3)(zod@3.25.51) - transitivePeerDependencies: - - debug - - typescript - - zod - solc@0.4.26: dependencies: fs-extra: 0.30.0 @@ -23549,23 +23609,11 @@ snapshots: transitivePeerDependencies: - debug - solc@0.8.25: - dependencies: - command-exists: 1.2.9 - commander: 8.3.0 - follow-redirects: 1.15.9(debug@4.4.1) - js-sha3: 0.8.0 - memorystream: 0.3.1 - semver: 5.7.2 - tmp: 0.0.33 - transitivePeerDependencies: - - debug - solc@0.8.26(debug@4.4.1): dependencies: command-exists: 1.2.9 commander: 8.3.0 - follow-redirects: 1.15.9(debug@4.4.1) + follow-redirects: 1.15.11(debug@4.4.1) js-sha3: 0.8.0 memorystream: 0.3.1 semver: 5.7.2 @@ -23573,16 +23621,19 @@ snapshots: transitivePeerDependencies: - debug - solhint@5.1.0(typescript@5.8.3): + solhint@6.0.0(typescript@5.8.3): dependencies: '@solidity-parser/parser': 0.20.1 ajv: 6.12.6 + ajv-errors: 1.0.1(ajv@6.12.6) antlr4: 4.13.2 ast-parents: 0.0.1 + better-ajv-errors: 2.0.2(ajv@6.12.6) chalk: 4.1.2 commander: 10.0.1 cosmiconfig: 8.3.6(typescript@5.8.3) fast-diff: 1.3.0 + fs-extra: 11.3.0 glob: 8.1.0 ignore: 5.3.2 js-yaml: 4.1.0 @@ -23730,8 +23781,6 @@ snapshots: sprintf-js@1.1.3: {} - src-location@1.1.0: {} - sshpk@1.18.0: dependencies: asn1: 0.2.6 @@ -24030,10 +24079,10 @@ snapshots: term-size@2.2.1: {} - terser@5.41.0: + terser@5.43.1: dependencies: - '@jridgewell/source-map': 0.3.6 - acorn: 8.14.1 + '@jridgewell/source-map': 0.3.10 + acorn: 8.15.0 commander: 2.20.3 source-map-support: 0.5.21 @@ -24306,7 +24355,7 @@ snapshots: - supports-color - typescript - typechain@8.3.2(patch_hash=zy6bsbkpcar7tt6jjbnwpaczsm)(typescript@5.8.3): + typechain@8.3.2(patch_hash=b34ed6afcf99760666fdc85ecb2094fdd20ce509f947eb09cef21665a2a6a1d6)(typescript@5.8.3): dependencies: '@types/prettier': 2.7.3 debug: 4.4.1(supports-color@9.4.0) @@ -24415,6 +24464,8 @@ snapshots: undici-types@6.19.8: {} + undici-types@6.21.0: {} + undici@5.29.0: dependencies: '@fastify/busboy': 2.1.1 @@ -24532,14 +24583,6 @@ snapshots: object.getownpropertydescriptors: 2.1.8 safe-array-concat: 1.1.3 - util@0.12.5: - dependencies: - inherits: 2.0.4 - is-arguments: 1.2.0 - is-generator-function: 1.1.0 - is-typed-array: 1.1.15 - which-typed-array: 1.1.19 - utils-merge@1.0.1: {} uuid@3.3.2: @@ -24646,10 +24689,6 @@ snapshots: - supports-color optional: true - web3-errors@1.3.1: - dependencies: - web3-types: 1.10.0 - web3-eth-abi@1.2.11: dependencies: '@ethersproject/abi': 5.0.0-beta.153 @@ -24657,17 +24696,6 @@ snapshots: web3-utils: 1.2.11 optional: true - web3-eth-abi@4.4.1(typescript@5.8.3)(zod@3.25.51): - dependencies: - abitype: 0.7.1(typescript@5.8.3)(zod@3.25.51) - web3-errors: 1.3.1 - web3-types: 1.10.0 - web3-utils: 4.3.3 - web3-validator: 2.0.6 - transitivePeerDependencies: - - typescript - - zod - web3-eth-accounts@1.2.11: dependencies: crypto-browserify: 3.12.0 @@ -24822,8 +24850,6 @@ snapshots: - supports-color optional: true - web3-types@1.10.0: {} - web3-utils@1.10.4: dependencies: '@ethereumjs/util': 8.1.0 @@ -24847,22 +24873,6 @@ snapshots: utf8: 3.0.0 optional: true - web3-utils@4.3.3: - dependencies: - ethereum-cryptography: 2.2.1 - eventemitter3: 5.0.1 - web3-errors: 1.3.1 - web3-types: 1.10.0 - web3-validator: 2.0.6 - - web3-validator@2.0.6: - dependencies: - ethereum-cryptography: 2.2.1 - util: 0.12.5 - web3-errors: 1.3.1 - web3-types: 1.10.0 - zod: 3.25.51 - web3@1.2.11(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: web3-bzz: 1.2.11(bufferutil@4.0.9)(utf-8-validate@5.0.10) @@ -25014,6 +25024,8 @@ snapshots: workerpool@6.5.1: {} + workerpool@9.3.3: {} + wrap-ansi@2.1.0: dependencies: string-width: 1.0.2 @@ -25094,6 +25106,11 @@ snapshots: bufferutil: 4.0.9 utf-8-validate: 5.0.10 + ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10): + optionalDependencies: + bufferutil: 4.0.9 + utf-8-validate: 5.0.10 + xhr-request-promise@0.1.3: dependencies: xhr-request: 1.1.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e783b8611..8c4c859cd 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,47 @@ packages: - - 'packages/*' - - 'packages/*/test' - - 'packages/*/task' + - packages/* + - packages/*/* + +catalog: + '@eslint/js': ^9.28.0 + '@nomicfoundation/hardhat-chai-matchers': ^2.0.0 + '@nomicfoundation/hardhat-ethers': ^3.0.8 + '@nomicfoundation/hardhat-foundry': ^1.1.1 + '@nomicfoundation/hardhat-ignition': 0.15.9 + '@nomicfoundation/hardhat-ignition-ethers': 0.15.9 + '@nomicfoundation/hardhat-network-helpers': ^1.0.9 + '@nomicfoundation/hardhat-toolbox': ^5.0.0 + '@nomicfoundation/hardhat-verify': ^2.0.10 + '@nomicfoundation/ignition-core': 0.15.9 + '@openzeppelin/contracts': ^5.3.0 + '@typechain/ethers-v5': ^10.2.1 + '@typechain/hardhat': ^9.0.0 + '@types/debug': ^4.1.12 + '@types/json5': ^2.2.0 + '@types/node': ^20.17.50 + '@wagmi/cli': ^2.3.1 + chai: ^4.2.0 + debug: ^4.4.0 + dotenv: ^16.5.0 + eslint: ^9.28.0 + eslint-config-prettier: ^10.1.5 + eslint-plugin-no-only-tests: ^3.3.0 + ethers: ^6.15.0 + glob: ^11.0.1 + hardhat: ^2.24.0 + hardhat-contract-sizer: ^2.10.0 + hardhat-dependency-compiler: ^1.2.1 + hardhat-gas-reporter: ^1.0.8 + hardhat-secure-accounts: ^1.0.5 + hardhat-storage-layout: ^0.1.7 + json5: ^2.2.3 + markdownlint-cli: ^0.45.0 + mocha: ^11.7.1 + prettier: ^3.5.3 + prettier-plugin-solidity: ^2.0.0 + solhint: ^6.0.0 + ts-node: ^10.9.2 + typechain: ^8.3.2 + typescript: ^5.8.3 + typescript-eslint: ^8.33.1 + viem: ^2.31.7 diff --git a/scripts/check-todos.sh b/scripts/check-todos.sh new file mode 100755 index 000000000..8bdb825f4 --- /dev/null +++ b/scripts/check-todos.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Check for TODO comments in Solidity files +# Can run during lint-staged (pre-commit) or regular linting (changed files only) + +# Exit on any error +set -e + +# Determine if we're running in lint-staged context or regular linting +LINT_STAGED_MODE=false +if [ "${LINT_STAGED:-}" = "true" ] || [ $# -gt 0 ]; then + LINT_STAGED_MODE=true +fi + +# If no files passed and not in lint-staged mode, check git changed files +if [ $# -eq 0 ] && [ "$LINT_STAGED_MODE" = false ]; then + # Get locally changed Solidity files (modified, added, but not committed) + CHANGED_FILES=$(git diff --name-only --diff-filter=AM HEAD | grep '\.sol$' || true) + # Get untracked Solidity files + UNTRACKED_FILES=$(git ls-files --others --exclude-standard | grep '\.sol$' || true) + # Combine both lists + ALL_FILES="$CHANGED_FILES $UNTRACKED_FILES" + if [ -z "$ALL_FILES" ]; then + echo "✅ No locally changed or untracked Solidity files to check for TODO comments." + exit 0 + fi + # Convert to array + set -- $ALL_FILES +fi + +# Check if any files to process +if [ $# -eq 0 ]; then + echo "✅ No files to check for TODO comments." + exit 0 +fi + +# Initialize flag to track if TODOs are found +TODO_FOUND=false + +# Check each file passed as argument +for file in "$@"; do + # Only check if file exists and is a Solidity file + if [ -f "$file" ] && [[ "$file" == *.sol ]]; then + # Search for TODO comments (case insensitive) + # Look for TODO, FIXME, XXX, HACK in comments + if grep -i -n -E "(//.*\b(todo|fixme|xxx|hack)\b|/\*.*\b(todo|fixme|xxx|hack)\b)" "$file" > /dev/null 2>&1; then + if [ "$TODO_FOUND" = false ]; then + echo "❌ TODO comments found in Solidity files:" + echo "" + TODO_FOUND=true + fi + echo "📝 $file:" + # Show the actual lines with TODO comments + grep -i -n -E "(//.*\b(todo|fixme|xxx|hack)\b|/\*.*\b(todo|fixme|xxx|hack)\b)" "$file" | while read -r line; do + echo " $line" + done + echo "" + fi + fi +done + +# Exit with error if TODOs were found +if [ "$TODO_FOUND" = true ]; then + if [ "$LINT_STAGED_MODE" = true ]; then + echo "❌ Please resolve all TODO comments in Solidity files before committing." + echo " This check runs during pre-commit to maintain code quality." + else + echo "❌ TODO comments found in locally changed Solidity files." + echo " Consider resolving these before committing." + fi + exit 1 +fi + +if [ "$LINT_STAGED_MODE" = true ]; then + echo "✅ No TODO comments found in Solidity files." +else + echo "✅ No TODO comments found in locally changed Solidity files." +fi +exit 0 diff --git a/scripts/lint-staged-run.sh b/scripts/lint-staged-run.sh new file mode 100755 index 000000000..d65f16599 --- /dev/null +++ b/scripts/lint-staged-run.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Lint-staged runner script +# Runs linting commands while excluding specific generated files +# Usage: lint-staged-run.sh [file2] ... + +set -e + +if [ $# -lt 2 ]; then + echo "Usage: $0 [file2] ..." + echo "Example: $0 'eslint --fix --cache' file1.js file2.ts" + exit 1 +fi + +COMMAND="$1" +shift +FILES=("$@") + +# Define ignore patterns for generated files that should never be linted despite being in git +IGNORE_PATTERNS=( + "*/.graphclient-extracted/*" +) + +# Function to check if a file should be ignored +should_ignore_file() { + local file="$1" + + for pattern in "${IGNORE_PATTERNS[@]}"; do + if [[ "$file" == $pattern ]]; then + return 0 # Should ignore + fi + done + + return 1 # Should not ignore +} + +# Filter files +FILTERED_FILES=() +for file in "${FILES[@]}"; do + if ! should_ignore_file "$file"; then + FILTERED_FILES+=("$file") + fi +done + +# If no files to process, exit successfully +if [ ${#FILTERED_FILES[@]} -eq 0 ]; then + exit 0 +fi + +# Execute command with filtered files +exec $COMMAND "${FILTERED_FILES[@]}" diff --git a/scripts/verify-solhint-disables.js b/scripts/verify-solhint-disables.js new file mode 100755 index 000000000..d1cf437fa --- /dev/null +++ b/scripts/verify-solhint-disables.js @@ -0,0 +1,299 @@ +#!/usr/bin/env node + +const fs = require('fs') +const { execSync } = require('child_process') + +/** + * Extract solhint-disable rules from a file's TODO section + */ +function extractDisabledRules(filePath) { + const content = fs.readFileSync(filePath, 'utf8') + const lines = content.split('\n') + + let inTodoSection = false + let disabledRules = [] + + for (const line of lines) { + // Handle TODO pattern + if (line.includes('TODO: Re-enable and fix issues')) { + inTodoSection = true + continue + } + + if (inTodoSection && line.trim().startsWith('// solhint-disable ')) { + const rulesStr = line.replace('// solhint-disable ', '').trim().replace(/,$/, '') + disabledRules = rulesStr + .split(',') + .map((r) => r.trim()) + .filter((r) => r) + break + } + + if (inTodoSection && !line.trim().startsWith('//')) { + break + } + + // Handle standalone solhint-disable + if (!inTodoSection && line.trim().startsWith('// solhint-disable ')) { + const rulesStr = line.replace('// solhint-disable ', '').trim().replace(/,$/, '') + disabledRules = rulesStr + .split(',') + .map((rule) => rule.trim()) + .filter((rule) => rule.length > 0) + break + } + } + + return disabledRules.sort() +} + +/** + * Get actual solhint issues for a file by sending content without TODO section via stdin + */ +function getActualIssues(filePath) { + try { + const content = fs.readFileSync(filePath, 'utf8') + + // Remove all lines starting with "// solhint-disable" + const cleanedLines = [] + + for (const line of content.split('\n')) { + if (!line.trim().startsWith('// solhint-disable ')) { + cleanedLines.push(line) + } + } + + const cleanedContent = cleanedLines.join('\n') + + // Write cleaned content to temporary file and run solhint from package root + const tempFile = filePath.replace('.sol', '.temp.sol') + fs.writeFileSync(tempFile, cleanedContent) + + try { + const result = execSync(`npx solhint ${tempFile} -f json`, { + encoding: 'utf8', + stdio: ['pipe', 'pipe', 'pipe'], + }) + + fs.unlinkSync(tempFile) // Clean up temp file + + const issues = JSON.parse(result) + const ruleIds = [...new Set(issues.map((issue) => issue.ruleId).filter((id) => id && id.trim()))].sort() + + return ruleIds + } catch (error) { + // Clean up temp file if it exists + if (fs.existsSync(tempFile)) { + fs.unlinkSync(tempFile) + } + console.error(`Error processing ${filePath}:`, error.message) + return [] + } + } catch (error) { + console.error(`Error reading ${filePath}:`, error.message) + return [] + } +} + +/** + * Fix disabled rules in a file + */ +function fixFile(filePath, actualIssues) { + const currentDisabledRules = extractDisabledRules(filePath) + + // Check if change is actually needed + const actualIssuesSorted = actualIssues.sort() + const currentRulesSorted = currentDisabledRules.sort() + + if (actualIssues.length === 0 && currentDisabledRules.length === 0) { + // Both empty - no change needed + return + } + + if ( + actualIssues.length > 0 && + actualIssuesSorted.length === currentRulesSorted.length && + actualIssuesSorted.every((rule, index) => rule === currentRulesSorted[index]) + ) { + // Rules match exactly - no change needed + return + } + const content = fs.readFileSync(filePath, 'utf8') + const lines = content.split('\n') + + const newLines = [] + let inTodoSection = false + let todoSectionEnded = false + let pragmaEndIndex = -1 + + // Find pragma end and TODO section + for (let i = 0; i < lines.length; i++) { + const line = lines[i] + + if (line.trim().startsWith('pragma ')) { + pragmaEndIndex = i + } + + if (line.includes('TODO: Re-enable and fix issues')) { + inTodoSection = true + continue + } + + if (inTodoSection && line.trim().startsWith('// solhint-disable')) { + continue // Skip old disable line + } + + if (inTodoSection && !line.trim().startsWith('//')) { + todoSectionEnded = true // TODO section has ended (moved past comments) + } + + if (inTodoSection && todoSectionEnded && line.trim() !== '') { + inTodoSection = false // No longer in TODO section when we hit non-blank + } + + if (!inTodoSection) { + newLines.push(line) + } + } + + // If no issues, remove TODO section entirely + if (actualIssues.length === 0) { + fs.writeFileSync(filePath, newLines.join('\n')) + return + } + + // Insert new TODO section after last pragma, skipping any existing blank lines + let insertIndex = pragmaEndIndex + 1 + + // Skip existing blank lines after pragma + while (insertIndex < newLines.length && newLines[insertIndex].trim() === '') { + insertIndex++ + } + + const todoSection = [ + '// TODO: Re-enable and fix issues when publishing a new version', + `// solhint-disable ${actualIssues.join(', ')}`, + '', + ] + + newLines.splice(insertIndex, 0, ...todoSection) + + fs.writeFileSync(filePath, newLines.join('\n')) +} + +/** + * Process all files that need TODO sections + */ +function processAllFiles(shouldFix = false) { + const contractsDir = 'contracts' + + // Find all .sol files + const allFilesResult = execSync(`find ${contractsDir} -name "*.sol"`, { + encoding: 'utf8', + }) + + const allFiles = allFilesResult + .trim() + .split('\n') + .filter((f) => f) + + console.log(`Processing ${allFiles.length} Solidity files...\n`) + + let correctFiles = 0 + let incorrectFiles = 0 + let fixedFiles = 0 + let noIssuesFiles = 0 + + for (const filePath of allFiles) { + const actualIssues = getActualIssues(filePath) + const disabledRules = extractDisabledRules(filePath) + + const extraRules = disabledRules.filter((rule) => !actualIssues.includes(rule)) + const missingRules = actualIssues.filter((rule) => !disabledRules.includes(rule)) + const isCorrect = extraRules.length === 0 && missingRules.length === 0 + + if (actualIssues.length === 0 && disabledRules.length === 0) { + // File has no issues and no TODO section - perfect + console.log(`✅ ${filePath} (no issues)`) + noIssuesFiles++ + correctFiles++ + } else if (actualIssues.length === 0 && disabledRules.length > 0) { + // File has no issues but has TODO section - should remove it + if (shouldFix) { + fixFile(filePath, actualIssues) + console.log(`🔧 ${filePath} - FIXED (removed unnecessary TODO)`) + fixedFiles++ + } else { + console.log(`❌ ${filePath}`) + console.log(` Should remove TODO section (no issues)`) + console.log(` Currently: [${disabledRules.join(', ')}]`) + console.log() + incorrectFiles++ + } + } else if (isCorrect) { + console.log(`✅ ${filePath}`) + correctFiles++ + } else { + if (shouldFix) { + fixFile(filePath, actualIssues) + console.log(`🔧 ${filePath} - FIXED`) + fixedFiles++ + } else { + console.log(`❌ ${filePath}`) + + if (extraRules.length > 0) { + console.log(` Extra rules (not needed): ${extraRules.join(', ')}`) + } + + if (missingRules.length > 0) { + console.log(` Missing rules (needed): ${missingRules.join(', ')}`) + } + + if (actualIssues.length === 0) { + console.log(` Should remove TODO section (no issues)`) + } else { + console.log(` Should be: ${actualIssues.join(', ')}`) + } + + console.log(` Currently: [${disabledRules.join(', ')}]`) + console.log() + + incorrectFiles++ + } + } + } + + console.log(`\nSummary:`) + console.log(`✅ Correct: ${correctFiles}`) + if (shouldFix) { + console.log(`🔧 Fixed: ${fixedFiles}`) + } else { + console.log(`❌ Incorrect: ${incorrectFiles}`) + } + console.log(`📄 No issues: ${noIssuesFiles}`) + console.log(`📊 Total: ${allFiles.length}`) + + if (!shouldFix && incorrectFiles > 0) { + process.exit(1) + } +} + +/** + * Main function + */ +function main() { + const args = process.argv.slice(2) + const shouldFix = args.includes('--fix') + + if (shouldFix) { + console.log('🔧 FIXING MODE: Will automatically update disabled rules\n') + } else { + console.log('🔍 VERIFICATION MODE: Use --fix to automatically update disabled rules\n') + } + + processAllFiles(shouldFix) +} + +if (require.main === module) { + main() +} diff --git a/tsconfig.json b/tsconfig.json index 5ede80f5b..9d236f5cc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es2020", + "target": "es2022", "module": "Node16", "moduleResolution": "node16", "esModuleInterop": true, @@ -14,6 +14,9 @@ "allowJs": true, "checkJs": false, "incremental": true, - "noEmitOnError": true + "noEmitOnError": true, + "paths": { + "@graphprotocol/*": ["./packages/*"] + } } } From 383951cf95df74e5f6f699720e210f8ad459f43c Mon Sep 17 00:00:00 2001 From: Rembrandt Kuipers Date: Thu, 14 Aug 2025 14:32:15 +0000 Subject: [PATCH 4/4] fix(contracts/task): fix TypeScript rootDir configuration - Remove restrictive rootDir setting that prevented imports from parent directories - Set rootDir to '..' to allow access to parent contracts types - Fixes CI build failure in packages/contracts/task TypeScript compilation Resolves TypeScript error TS6059 where files outside rootDir were being imported --- packages/contracts/task/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts/task/tsconfig.json b/packages/contracts/task/tsconfig.json index f866f8173..f60d075ba 100644 --- a/packages/contracts/task/tsconfig.json +++ b/packages/contracts/task/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "rootDir": ".", + "rootDir": "..", "outDir": "./build", "declarationDir": "./types" },